├── docker └── README.md ├── learn └── README.md ├── contracts ├── erc1155 │ ├── README.md │ ├── deploy │ │ └── hardhat_deploy.ts │ └── contracts │ │ └── MyToken.sol ├── erc721 │ ├── README.md │ ├── contracts │ │ └── MyCollection.sol │ └── deploy │ │ └── hardhat_deploy.ts ├── soulbound-nft │ ├── README.md │ ├── deploy │ │ └── hardhat_deploy.ts │ └── contracts │ │ └── SoulboundNFT.sol ├── CoinFlip │ ├── node_modules │ ├── .env │ ├── .gitignore │ ├── README.md │ ├── utils │ │ └── verify.js │ ├── test │ │ └── CoinFlip.t.js │ ├── deploy │ │ └── deployCoinFlip.s.js │ ├── hardhat.config.js │ └── contract │ │ └── CoinFlip.sol ├── README.md ├── ContriBoost │ ├── hardhat.config.js │ ├── .gitignore │ ├── package.json │ ├── deploy │ │ └── script.js │ ├── contracts │ │ ├── FactoryContribute.sol │ │ └── Contribute.sol │ └── README.md ├── MultiTierReferralSystem │ ├── .env.example │ ├── tsconfig.json │ ├── .gitignore │ ├── contracts │ │ ├── ExampleUSDC.sol │ │ └── MultiTierReferralSystem.sol │ ├── README.md │ ├── ignition │ │ └── modules │ │ │ └── MultiTierReferralSystem.ts │ ├── hardhat.config.ts │ └── test │ │ └── MultiTierReferralSystem.test.ts ├── erc5115 │ ├── foundry.toml │ ├── README.md │ ├── remappings.txt │ ├── src │ │ ├── interfaces │ │ │ ├── IRewardManager.sol │ │ │ ├── IYearnVault.sol │ │ │ └── IStandardizedYield.sol │ │ ├── libraries │ │ │ ├── SYUtils.sol │ │ │ ├── SYMath.sol │ │ │ └── TokenHelper.sol │ │ ├── abstracts │ │ │ ├── SYBaseWithRewards.sol │ │ │ ├── RewardManager.sol │ │ │ └── SYBase.sol │ │ └── samples │ │ │ └── YearnVaultSY.sol │ └── test │ │ └── YearnVault.t.sol ├── EduChain │ ├── .gitignore │ ├── hardhat.config.js │ ├── ignition │ │ └── modules │ │ │ └── Lock.js │ ├── test │ │ └── Lock.js │ ├── contracts │ │ └── FactorySchool.sol │ └── README.md ├── crowd-fund │ ├── README.md │ └── CrowdFund.sol ├── Minimal Proxy │ ├── masterContract.sol │ ├── README.md │ └── minimalProxy.sol ├── election │ ├── README.md │ └── election.sol ├── erc2981 │ ├── README.md │ ├── deploy │ │ └── hardhat_deploy.ts │ ├── contracts │ │ ├── ERC721-example.sol │ │ └── ERC1155-example.sol │ └── test │ │ ├── erc1155.test.js │ │ └── erc721.test.js ├── erc4626 │ ├── contracts │ │ ├── MyToken.sol │ │ └── MyVault.sol │ ├── README.md │ └── tests │ │ └── MyVault_foundry_test.sol ├── timelock │ ├── MyToken.sol │ └── README.md ├── erc20 │ ├── contracts │ │ └── MyToken.sol │ ├── deploy │ │ └── hardhat_deploy.ts │ ├── tests │ │ ├── MyToken_foundry_test.sol │ │ ├── MyToken_remix_test.sol │ │ └── MyToken_hardhat_test.ts │ └── README.md ├── gaslite-airdrop │ ├── README.md │ ├── deploy │ │ └── hardhat_deploy.ts │ └── contracts │ │ └── GasliteDrop.sol ├── erc3156 │ ├── contracts │ │ ├── mocks │ │ │ └── ERC20Mock.sol │ │ ├── reference │ │ │ ├── mocks │ │ │ │ └── ERC20FlashMintMock.sol │ │ │ ├── FlashMinter.sol │ │ │ └── FlashLender.sol │ │ ├── interfaces │ │ │ ├── IERC3156FlashBorrower.sol │ │ │ ├── IERC3156FlashLender.sol │ │ │ └── IERC20.sol │ │ ├── FlashBorrower.sol │ │ └── ERC20.sol │ ├── deploy │ │ ├── FlashBorrower.js │ │ ├── FlashMinter.js │ │ └── FlashLender.js │ ├── test │ │ ├── 01_FlashMinter.test.js │ │ └── 02_FlashLender.test.js │ └── testlog.txt ├── dutch-auction │ ├── deploy │ │ └── hardhat_deploy.ts │ └── contracts │ │ └── DutchAuction.sol └── english-auction │ ├── deploy │ └── hardhat_deploy.ts │ └── contracts │ └── EnglishAuction.sol ├── .gitignore ├── frontend ├── wagmi │ ├── wagmi-v1 │ │ └── connect-wallet │ │ │ └── README.md │ ├── wagmi-v2 │ │ ├── connect-wallet │ │ │ ├── web3modal │ │ │ │ ├── react-vite-ts │ │ │ │ │ ├── README.md │ │ │ │ │ ├── public │ │ │ │ │ │ └── Klaytn_Symbol.png │ │ │ │ │ ├── App.tsx │ │ │ │ │ └── context │ │ │ │ │ │ └── index.tsx │ │ │ │ └── nextjs-14-app-router │ │ │ │ │ └── README.md │ │ │ └── README.md │ │ └── setup-wagmi-v2 │ │ │ ├── nextjs-14-app-router │ │ │ ├── README.md │ │ │ └── app │ │ │ │ ├── layout.tsx │ │ │ │ ├── config.ts │ │ │ │ └── providers.tsx │ │ │ ├── react-vite-ts │ │ │ ├── App.tsx │ │ │ └── config.ts │ │ │ └── README.md │ └── README.md └── network │ └── add-network-button.tsx ├── dapps └── README.md ├── klaytn-hacker-house ├── on-site-sessions │ └── gmvietnam-hackerhouse │ │ ├── submissions.md │ │ ├── registrations.md │ │ ├── README.md │ │ └── rules.md └── README.md ├── .DS_Store ├── home-banner.png ├── .vscode └── settings.json ├── docs └── README.md ├── .github └── ISSUE_TEMPLATE │ └── proposal-for-bounty-submission.md ├── SECURITY.md ├── workshops └── webinar-vietnam-08-05-2024 │ ├── submissions │ └── Exercise_zxstim.sol │ ├── Exercise.sol │ ├── README.md │ └── Exercise_test.sol ├── LICENSE ├── README.md ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /docker/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /learn/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/erc1155/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/erc721/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | .vscode -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v1/connect-wallet/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/soulbound-nft/README.md: -------------------------------------------------------------------------------- 1 | # Soulbound NFT 2 | -------------------------------------------------------------------------------- /dapps/README.md: -------------------------------------------------------------------------------- 1 | # List of DApps that won bounty on Dorahacks -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/web3modal/react-vite-ts/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/submissions.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/klaytn-dapp-toolkit/HEAD/.DS_Store -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/web3modal/nextjs-14-app-router/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/CoinFlip/node_modules: -------------------------------------------------------------------------------- 1 | /home/paul-eth/Hardhat-CoinFlip-SmartContract/node_modules -------------------------------------------------------------------------------- /home-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/klaytn-dapp-toolkit/HEAD/home-banner.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "solidity.compileUsingRemoteVersion": "v0.8.23+commit.f704f362" 3 | } -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/nextjs-14-app-router/README.md: -------------------------------------------------------------------------------- 1 | # Setup Wagmi v2 for Nextjs 14 App router project 2 | 3 | -------------------------------------------------------------------------------- /contracts/CoinFlip/.env: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=PRIVATE_KEY 2 | KLAYTN_RPC=https://api.baobab.klaytn.net:8651 3 | ETHERSCAN_API_KEY=CA6ZQJMSVZMVYSI57GF5TP69UQPM1753Z7 -------------------------------------------------------------------------------- /contracts/README.md: -------------------------------------------------------------------------------- 1 | # Smart contracts 2 | 3 | A collection of ready to deploy smart contracts with deployment scripts and test files 4 | 5 | ## Guide 6 | 7 | -------------------------------------------------------------------------------- /contracts/ContriBoost/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomicfoundation/hardhat-toolbox"); 2 | 3 | /** @type import('hardhat/config').HardhatUserConfig */ 4 | module.exports = { 5 | solidity: "0.8.24", 6 | }; 7 | -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY="" 2 | ETHERSCAN_API_KEY="" 3 | KLAY_MAINNET_URL="https://public-en-cypress.klaytn.net" 4 | KLAY_TESTNET_URL="https://public-en-baobab.klaytn.net" 5 | REPORT_GAS=true -------------------------------------------------------------------------------- /contracts/erc5115/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "src" 3 | out = "out" 4 | libs = ["lib"] 5 | 6 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 7 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/web3modal/react-vite-ts/public/Klaytn_Symbol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klaytn/klaytn-dapp-toolkit/HEAD/frontend/wagmi/wagmi-v2/connect-wallet/web3modal/react-vite-ts/public/Klaytn_Symbol.png -------------------------------------------------------------------------------- /contracts/CoinFlip/.gitignore: -------------------------------------------------------------------------------- 1 | ./node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json -------------------------------------------------------------------------------- /contracts/EduChain/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json 15 | -------------------------------------------------------------------------------- /contracts/erc5115/README.md: -------------------------------------------------------------------------------- 1 | ERC5115: A token standard for a yield-generating mechanism. 2 | 3 | You can learn more about this standard by reading the ERC5115 [https://github.com/pendle-finance/pendle-v2-resources/blob/main/whitepapers/SY.pdf](White paper). -------------------------------------------------------------------------------- /contracts/crowd-fund/README.md: -------------------------------------------------------------------------------- 1 | # Crowd Fund contract 2 | 3 | 4 | ## Getting started 5 | 1. Deploy a token 6 | 7 | ## Deployed implementation on Testnet 8 | https://baobab.klaytnscope.com/tx/0xf029c9d3ed58d304d3fbc413aa6766a66f6ef698421cd9b3c5c786cf99fb555a 9 | -------------------------------------------------------------------------------- /contracts/Minimal Proxy/masterContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract MasterContract { 5 | uint public value; 6 | 7 | function setValue(uint _value) external { 8 | value = _value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/CoinFlip/README.md: -------------------------------------------------------------------------------- 1 | ### CoinFlip 2 | 3 | A coin toss game smart contract that implements the functionality which allows a user to pay klay to flip/toss a coin and gets double the amount staked if the chosen side is equal to the coin landing side using orakl vrf for randomness. -------------------------------------------------------------------------------- /contracts/election/README.md: -------------------------------------------------------------------------------- 1 | # Election contract 2 | 3 | 4 | 5 | ## Deployed and verified implementation on Testnet 6 | View deployed and verified implementation on [Klaytnscope](https://baobab.klaytnscope.com/account/0xc668e9230bA83aCA24d2C97B449E05a1278c9446?tabId=contractCode) 7 | -------------------------------------------------------------------------------- /contracts/erc2981/README.md: -------------------------------------------------------------------------------- 1 | # ERC2981 contract 2 | 3 | ## Getting started 4 | 5 | ERC 2981 is a standard way to encode royalty information in a smart contract. This helps ensure that the NFT creator or rights holder gets paid the correct amount of royalties every time the NFT is sold or re-sold. 6 | -------------------------------------------------------------------------------- /contracts/erc5115/remappings.txt: -------------------------------------------------------------------------------- 1 | @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ 2 | ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/ 3 | erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/ 4 | forge-std/=lib/forge-std/src/ 5 | openzeppelin-contracts/=lib/openzeppelin-contracts/ 6 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Klaytn DApp Toolkit docs 2 | This DApp Toolkit docs is an extension of the official [Klaytn Foundation Docs](https://docs.klaytn.foundation). Feel free to refer to the official documentation for all the core concepts about Klaytn blockchain. This docs section will focus only on DApp development. 3 | 4 | Topics 5 | -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /contracts/erc4626/contracts/MyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract MyToken is ERC20 { 7 | constructor(address _addr) ERC20("MyToken", "MTK") { 8 | _mint(_addr, 1000 * 10 ** decimals()); 9 | } 10 | } -------------------------------------------------------------------------------- /contracts/erc5115/src/interfaces/IRewardManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | interface IRewardManager { 5 | function userRewardAccrued(address token, address user) external view returns (uint256); 6 | 7 | function rewardState(address token) external view returns (uint256 index, uint256 lastBalance); 8 | } -------------------------------------------------------------------------------- /contracts/timelock/MyToken.sol: -------------------------------------------------------------------------------- 1 | // contracts/GLDToken.sol 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MyToken is ERC20 { 8 | constructor(uint256 initialSupply) ERC20("MyToken", "MTK") { 9 | _mint(msg.sender, initialSupply); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /contracts/ContriBoost/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json 15 | 16 | # Hardhat Ignition default folder for deployments against a local node 17 | ignition/deployments/chain-31337 18 | -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json 15 | 16 | # Hardhat Ignition default folder for deployments against a local node 17 | ignition/deployments/chain-31337 18 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/web3modal/react-vite-ts/App.tsx: -------------------------------------------------------------------------------- 1 | import './App.css' 2 | import Web3Modal from './context' 3 | 4 | 5 | function App() { 6 | 7 | return ( 8 | 9 |
10 |
11 | {/** ... */} 12 |
13 |
14 |
15 | ) 16 | } 17 | 18 | export default App 19 | -------------------------------------------------------------------------------- /contracts/erc20/contracts/MyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | /// @custom:security-contact your.email@company.com 7 | contract MyToken is ERC20 { 8 | constructor(address _addr) ERC20("MyToken", "MTK") { 9 | _mint(_addr, 1000 * 10 ** decimals()); 10 | } 11 | } -------------------------------------------------------------------------------- /contracts/erc5115/src/interfaces/IYearnVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | interface IYearnVault { 6 | function deposit(uint256 amount) external returns (uint256); 7 | 8 | function withdraw(uint256 maxShares) external returns (uint256); 9 | 10 | function pricePerShare() external view returns (uint256); 11 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/proposal-for-bounty-submission.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Proposal for bounty submission 3 | about: Use this template to submit a proposal for any bounty tracks 4 | title: 'Proposal: [name_of_proposal]' 5 | labels: '' 6 | assignees: zxstim 7 | 8 | --- 9 | 10 | Description 11 | - [describe what the submission is] 12 | 13 | Bounty track 14 | - [add the name of the bounty track here] 15 | -------------------------------------------------------------------------------- /contracts/erc4626/contracts/MyVault.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; 5 | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MyVault is ERC4626 { 8 | constructor(address asset) ERC4626(IERC20(asset)) ERC20("myVault", "MYVAULT") { 9 | } 10 | } -------------------------------------------------------------------------------- /contracts/erc721/contracts/MyCollection.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.24; 3 | 4 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | 6 | contract MyCollection is ERC721 { 7 | constructor() ERC721("MyCollection", "MCN") {} 8 | 9 | function _baseURI() internal pure override returns (string memory) { 10 | return "https://mycollection.com/"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/EduChain/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomicfoundation/hardhat-toolbox"); 2 | require('dotenv').config() 3 | 4 | 5 | module.exports = { 6 | solidity: "0.8.17", 7 | networks: { 8 | baobab: { 9 | url: process.env.KLAYTN_BAOBAB_URL || "", 10 | gasPrice: 250000000000, 11 | accounts: 12 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /contracts/Minimal Proxy/README.md: -------------------------------------------------------------------------------- 1 | # EIP-1167 Minimal Proxy Contract 2 | ## This repository contains a master contract that is cloned and deployed using an EIP-1167 minimal Proxy contract 3 | ### Rather than deploying an entire contract for each user or operation, incurring high gas fees, a cost-effective approach involves deploying a minimal proxy contract that references the existing full contract already present on the blockchain. 4 | -------------------------------------------------------------------------------- /contracts/gaslite-airdrop/README.md: -------------------------------------------------------------------------------- 1 | # Gaslite version Airdrop 2 | 3 | ## Introduction 4 | Created by: 5 | - [Harrison](https://twitter.com/PopPunkOnChain) 6 | - [Gaslite](https://twitter.com/GasliteGG) 7 | - [Pop Punk LLC](https://twitter.com/PopPunkLLC) 8 | 9 | ## Compiler Configuration 10 | - Compiler Version: `v0.8.19+commit.7dd6d404` 11 | - EVM Version: `paris` 12 | - Optimization Used: `1` 13 | - Proxy: `0` 14 | - Runs: `9999999` -------------------------------------------------------------------------------- /contracts/erc3156/contracts/mocks/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../ERC20.sol"; 5 | 6 | contract ERC20Mock is ERC20 { 7 | 8 | constructor (string memory name, string memory symbol) ERC20(name, symbol) {} 9 | 10 | /// @dev Give free tokens to anyone 11 | function mint(address receiver, uint256 amount) external { 12 | _mint(receiver, amount); 13 | } 14 | } -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/contracts/ExampleUSDC.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract ExampleUSDC is ERC20("USDC", "USDC") { 7 | constructor() { 8 | _mint(_msgSender(), 1000000000e6); 9 | } 10 | 11 | function decimals() public view virtual override returns (uint8) { 12 | return 6; 13 | } 14 | } -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/README.md: -------------------------------------------------------------------------------- 1 | # Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a Hardhat Ignition module that deploys that contract. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat help 9 | npx hardhat test 10 | REPORT_GAS=true npx hardhat test 11 | npx hardhat node 12 | npx hardhat ignition deploy ./ignition/modules/Lock.ts 13 | ``` 14 | -------------------------------------------------------------------------------- /contracts/timelock/README.md: -------------------------------------------------------------------------------- 1 | # Simple Timelock Contract 2 | ## This repository contains an ERC20 CONTRACT that makes use of a Timelock Contract 3 | ### The provided code is a Solidity smart contract named SimpleTimelock. It implements a time-locked mechanism for an ERC20 token. A time-lock mechanism ensures that certain actions can only occur after a specific amount of time has passed. This contract uses OpenZeppelin libraries for safe operations with ERC20 tokens and mathematical calculations 4 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/reference/mocks/ERC20FlashMintMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../FlashMinter.sol"; 5 | 6 | contract FlashMinterMock is FlashMinter { 7 | 8 | constructor (string memory name, string memory symbol, uint256 fee) FlashMinter(name, symbol, fee) {} 9 | 10 | /// @dev Give free tokens to anyone 11 | function mint(address receiver, uint256 amount) external { 12 | _mint(receiver, amount); 13 | } 14 | } -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/react-vite-ts/App.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query' 2 | import { WagmiProvider } from 'wagmi' 3 | import { config } from './config' 4 | 5 | const queryClient = new QueryClient() 6 | 7 | function App() { 8 | return ( 9 | 10 | 11 | {/** ... */} 12 | 13 | 14 | ) 15 | } -------------------------------------------------------------------------------- /contracts/ContriBoost/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "contriboost", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@nomicfoundation/hardhat-toolbox": "^5.0.0", 13 | "hardhat": "^2.22.3" 14 | }, 15 | "dependencies": { 16 | "@klaytn/contracts": "^1.0.6", 17 | "dotenv": "^16.4.5" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/erc20/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const myToken = await ethers.deployContract("MyToken"); 6 | 7 | await myToken.waitForDeployment(); 8 | 9 | console.log( 10 | `MyToken was deployed to ${myToken.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/erc1155/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const myToken = await ethers.deployContract("MyToken"); 6 | 7 | await myToken.waitForDeployment(); 8 | 9 | console.log( 10 | `MyToken was deployed to ${myToken.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/erc2981/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | const myCollection = await ethers.deployContract("ERC721Example"); 5 | 6 | await myCollection.waitForDeployment(); 7 | 8 | console.log(`MyCollection was deployed to ${myCollection.target}`); 9 | } 10 | 11 | // We recommend this pattern to be able to use async/await everywhere 12 | // and properly handle errors. 13 | main().catch((error) => { 14 | console.error(error); 15 | process.exitCode = 1; 16 | }); 17 | -------------------------------------------------------------------------------- /contracts/EduChain/ignition/modules/Lock.js: -------------------------------------------------------------------------------- 1 | const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); 2 | 3 | const JAN_1ST_2030 = 1893456000; 4 | const ONE_GWEI = 1_000_000_000n; 5 | 6 | module.exports = buildModule("LockModule", (m) => { 7 | const unlockTime = m.getParameter("unlockTime", JAN_1ST_2030); 8 | const lockedAmount = m.getParameter("lockedAmount", ONE_GWEI); 9 | 10 | const lock = m.contract("Lock", [unlockTime], { 11 | value: lockedAmount, 12 | }); 13 | 14 | return { lock }; 15 | }); 16 | -------------------------------------------------------------------------------- /contracts/erc5115/src/libraries/SYUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | library SCYUtils { 5 | uint256 internal constant ONE = 1e18; 6 | 7 | function scyToAsset(uint256 exchangeRate, uint256 scyAmount) internal pure returns (uint256) { 8 | return (scyAmount * exchangeRate) / ONE; 9 | } 10 | 11 | function assetToScy(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) { 12 | return (assetAmount * ONE) / exchangeRate; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/erc721/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const myCollection = await ethers.deployContract("MyCollection"); 6 | 7 | await myCollection.waitForDeployment(); 8 | 9 | console.log( 10 | `MyCollection was deployed to ${myCollection.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/dutch-auction/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const dutchAuction = await ethers.deployContract("DutchAuction"); 6 | 7 | await dutchAuction.waitForDeployment(); 8 | 9 | console.log( 10 | `DutchAuction was deployed to ${dutchAuction.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/erc3156/deploy/FlashBorrower.js: -------------------------------------------------------------------------------- 1 | const func = async function ({ deployments, getNamedAccounts, getChainId }) { 2 | const { deploy, read, execute } = deployments 3 | const { deployer } = await getNamedAccounts() 4 | const chainId = await getChainId() 5 | 6 | const borrower = await deploy('FlashBorrower', { 7 | from: deployer, 8 | deterministicDeployment: true, 9 | }) 10 | console.log(`Deployed FlashBorrower to ${borrower.address}`) 11 | } 12 | 13 | module.exports = func 14 | module.exports.tags = ["FlashBorrower"] -------------------------------------------------------------------------------- /contracts/soulbound-nft/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const soulboundNFT = await ethers.deployContract("SoulboundNFT"); 6 | 7 | await soulboundNFT.waitForDeployment(); 8 | 9 | console.log( 10 | `SoulboundNFT was deployed to ${soulboundNFT.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/react-vite-ts/config.ts: -------------------------------------------------------------------------------- 1 | import { http, createConfig } from 'wagmi' 2 | import { klaytn, klaytnBaobab } from 'wagmi/chains' 3 | 4 | // Create wagmiConfig 5 | export const config = createConfig({ 6 | chains: [ klaytn, klaytnBaobab ], 7 | transports: { 8 | [klaytn.id]: http("https://rpc.ankr.com/klaytn"), // you can replace the http() with any other RPC URL you like 9 | [klaytnBaobab.id]: http("https://rpc.ankr.com/klaytn_testnet") // you can replace the http() with any other RPC URL you like 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /contracts/gaslite-airdrop/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const gasliteAirdrop = await ethers.deployContract("GasliteDrop"); 6 | 7 | await gasliteAirdrop.waitForDeployment(); 8 | 9 | console.log( 10 | `GasliteDrop was deployed to ${gasliteAirdrop.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/english-auction/deploy/hardhat_deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | 5 | const englishAuction = await ethers.deployContract("EnglishAuction"); 6 | 7 | await englishAuction.waitForDeployment(); 8 | 9 | console.log( 10 | `EnglishAuction was deployed to ${englishAuction.target}` 11 | ); 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main().catch((error) => { 17 | console.error(error); 18 | process.exitCode = 1; 19 | }); 20 | -------------------------------------------------------------------------------- /contracts/erc5115/src/libraries/SYMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import "@openzeppelin/contracts/utils/math/Math.sol"; 6 | 7 | library SYMath { 8 | uint256 internal constant ONE = 1e18; // 18 decimal places 9 | 10 | using Math for uint256; 11 | 12 | function mulDown(uint256 a, uint256 b) internal pure returns (uint256) { 13 | return a.mulDiv(b, ONE); 14 | } 15 | 16 | function divDown(uint256 a, uint256 b) internal pure returns (uint256) { 17 | return a.mulDiv(ONE, b); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/CoinFlip/utils/verify.js: -------------------------------------------------------------------------------- 1 | import run from "hardhat" 2 | 3 | const verify = async (contractAddress, args) => { 4 | console.log("Verifying contract....") 5 | try { 6 | await run("verify:verify", { 7 | address: contractAddress, 8 | constructorArgs: args 9 | }) 10 | } catch (error) { 11 | if (error.message.toLowerCase().includes("already verified")) { 12 | console.log("Already verified...!") 13 | } else { 14 | console.log(error); 15 | } 16 | } 17 | } 18 | 19 | module.exports = { 20 | verify 21 | } -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/README.md: -------------------------------------------------------------------------------- 1 | # Connect wallet with Wagmi v2 2 | > Choose the frameworks that you use and check out the code snippets 3 | 4 | ## web3modal 5 | The Web3Modal SDK allows you to easily connect your Web3 dapp with wallets. It provides a simple and intuitive interface for dapps to request actions such as signing transactions and interacting with smart contracts on the blockchain. 6 | 7 | Web3Modal support for Wagmi v2 is still beta so you will encounter some issues, especially with Nextjs 14 App router which relies on SSR and RSC. 8 | 9 | ## web3modal-klaytn 10 | 11 | 12 | ## connectkit 13 | 14 | 15 | ## rainbowkit 16 | 17 | 18 | ## rabbykit 19 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/nextjs-14-app-router/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { type ReactNode } from 'react' 2 | import { headers } from 'next/headers' 3 | import { cookieToInitialState } from 'wagmi' 4 | 5 | import { config } from './config' 6 | import { Providers } from './providers' 7 | 8 | export default function Layout({ children }: { children: ReactNode }) { 9 | const initialState = cookieToInitialState( 10 | config, 11 | headers().get('cookie') 12 | ) 13 | return ( 14 | 15 | 16 | 17 | {children} 18 | 19 | 20 | 21 | ) 22 | } -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/nextjs-14-app-router/app/config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createConfig, 3 | http, 4 | cookieStorage, 5 | createStorage 6 | } from 'wagmi' 7 | import { klaytn, klaytnBaobab } from 'wagmi/chains' 8 | 9 | export const config = createConfig({ 10 | chains: [klaytn, klaytnBaobab], 11 | ssr: true, 12 | storage: createStorage({ 13 | storage: cookieStorage, 14 | }), 15 | transports: { 16 | [klaytn.id]: http("https://rpc.ankr.com/klaytn"), // you can replace the http() with any other RPC URL you like 17 | [klaytnBaobab.id]: http("https://rpc.ankr.com/klaytn_testnet") // you can replace the http() with any other RPC URL you like 18 | }, 19 | }) -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | Klaytn Foundation and community take security bugs in our repositories seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. 4 | 5 | To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/klaytn/klaytn-dapp-toolkit/security/advisories/new) tab. 6 | 7 | Klaytn Foundation will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. 8 | -------------------------------------------------------------------------------- /contracts/ContriBoost/deploy/script.js: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | async function main() { 3 | // We get the contract to deploy 4 | const ContributionSystemFactory = await ethers.deployContract("ContributionSystemFactory"); 5 | await ContributionSystemFactory.waitForDeployment(); 6 | console.log("Deploying ContributionSystemFactory..."); 7 | await ContributionSystemFactory.deployed(); 8 | console.log( 9 | `Contribution System Factory was deployed to ${ContributionSystemFactory.target}` 10 | ); 11 | } 12 | 13 | main() 14 | .then(() => process.exit(0)) 15 | .catch((error) => { 16 | console.error(error); 17 | process.exit(1); 18 | }); 19 | 20 | 21 | -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/ignition/modules/MultiTierReferralSystem.ts: -------------------------------------------------------------------------------- 1 | import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; 2 | 3 | const MultiTierReferralSystem = buildModule("MultiTierReferralSystem", (m) => { 4 | const usdcAddress = "0x754288077d0ff82af7a5317c7cb8c444d421d103"; // Example oUSDC (https://klaytnscope.com/token/0x754288077d0ff82af7a5317c7cb8c444d421d103) 5 | const defaultUpline = "0x0fFee57EAA1026857E381BC51B6832735006fc6a"; // Example Default Upline (Platform Address) 6 | const multiTierReferralSystem = m.contract("MultiTierReferralSystem", [usdcAddress, defaultUpline]); 7 | 8 | return { multiTierReferralSystem }; 9 | }); 10 | 11 | export default MultiTierReferralSystem; 12 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/nextjs-14-app-router/app/providers.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query' 4 | import type { ReactNode } from 'react' 5 | import { type State, WagmiProvider } from 'wagmi' 6 | 7 | import { config } from './config' 8 | 9 | type Props = { 10 | children: ReactNode, 11 | initialState: State, 12 | } 13 | 14 | const queryClient = new QueryClient() 15 | 16 | export function Providers({ children, initialState }: Props) { 17 | return ( 18 | 19 | 20 | {children} 21 | 22 | 23 | ) 24 | } -------------------------------------------------------------------------------- /contracts/erc2981/contracts/ERC721-example.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | import "@openzeppelin/contracts/token/common/ERC2981.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 6 | 7 | contract ERC721Example is ERC721, ERC2981 { 8 | constructor() ERC721("Name", "Symbol") { 9 | // set royalty of all NFTs to 5% 10 | _setDefaultRoyalty(_msgSender(), 500); 11 | } 12 | 13 | function mint(address to, uint256 tokenId) public { 14 | _safeMint(to, tokenId); 15 | } 16 | 17 | function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) { 18 | return super.supportsInterface(interfaceId); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /workshops/webinar-vietnam-08-05-2024/submissions/Exercise_zxstim.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | // There are 3 functions in this Counter contract. Each function has a mistake that you have to fix to be able to pass all the test cases in the test file 5 | 6 | contract Counter { 7 | uint256 public count; 8 | 9 | // Function to get the current count. Make sure the function doesn't modify the value of count. 10 | function get() public view returns (uint256) { 11 | return count; 12 | } 13 | 14 | // Function to increment count by 1 15 | function increment() public { 16 | count -= 1; 17 | } 18 | 19 | // Function to decrement count by 1 20 | function decrement() public { 21 | count += 1; 22 | } 23 | } -------------------------------------------------------------------------------- /workshops/webinar-vietnam-08-05-2024/Exercise.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | // There are 3 functions in this Counter contract. Each function has a mistake that you have to fix to be able to pass all the test cases in the test file 5 | 6 | contract Counter { 7 | uint256 public count; 8 | 9 | // Function to get the current count. Make sure the function doesn't modify the value of count. 10 | function get() public view returns (uint256) { 11 | count = 1; 12 | return count; 13 | } 14 | 15 | // Function to increment count by 1 16 | function increment() public { 17 | count -= 1; 18 | } 19 | 20 | // Function to decrement count by 1 21 | function decrement() public { 22 | count += 1; 23 | } 24 | } -------------------------------------------------------------------------------- /contracts/erc3156/contracts/interfaces/IERC3156FlashBorrower.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.0 <0.9.0; 3 | 4 | 5 | interface IERC3156FlashBorrower { 6 | 7 | /** 8 | * @dev Receive a flash loan. 9 | * @param initiator The initiator of the loan. 10 | * @param token The loan currency. 11 | * @param amount The amount of tokens lent. 12 | * @param fee The additional amount of tokens to repay. 13 | * @param data Arbitrary data structure, intended to contain user-defined parameters. 14 | * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" 15 | */ 16 | function onFlashLoan( 17 | address initiator, 18 | address token, 19 | uint256 amount, 20 | uint256 fee, 21 | bytes calldata data 22 | ) external returns (bytes32); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/erc3156/deploy/FlashMinter.js: -------------------------------------------------------------------------------- 1 | const func = async function ({ deployments, getNamedAccounts, getChainId }) { 2 | const { deploy, read, execute } = deployments; 3 | const { deployer } = await getNamedAccounts(); 4 | const chainId = await getChainId() 5 | 6 | if (chainId === '31337') { // buidlerevm's chainId 7 | console.log('Local deployments not implemented') 8 | return 9 | } else { 10 | const lender = await deploy('FlashMinter', { 11 | from: deployer, 12 | deterministicDeployment: true, 13 | args: [ 14 | "FlashMinter", 15 | "FLS", 16 | "115792089237316195423570985008687907853269984665640564039457584007913129639935", 17 | ], 18 | }) 19 | console.log(`Deployed FlashMinter to ${lender.address}`); 20 | } 21 | }; 22 | 23 | module.exports = func; 24 | module.exports.tags = ["FlashMinter"]; -------------------------------------------------------------------------------- /contracts/erc2981/contracts/ERC1155-example.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | import "@openzeppelin/contracts/token/common/ERC2981.sol"; 5 | import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 6 | 7 | contract ERC1155Example is ERC1155, ERC2981 { 8 | constructor() ERC1155("ipfs://example/{id}.json") { 9 | // set royalty of all NFTs to 5% 10 | _setDefaultRoyalty(_msgSender(), 500); 11 | } 12 | 13 | function mint( 14 | address to, 15 | uint256 tokenId, 16 | uint256 amount, 17 | bytes memory data 18 | ) public { 19 | _mint(to, tokenId, amount, data); 20 | } 21 | 22 | function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155, ERC2981) returns (bool) { 23 | return super.supportsInterface(interfaceId); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/erc1155/contracts/MyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | /// @custom:security-contact name@domain.com 8 | contract MyToken is ERC1155, Ownable { 9 | constructor(address initialOwner) 10 | ERC1155("https://mytoken.com/") 11 | Ownable(initialOwner) 12 | {} 13 | 14 | function mint(address account, uint256 id, uint256 amount, bytes memory data) 15 | public 16 | onlyOwner 17 | { 18 | _mint(account, id, amount, data); 19 | } 20 | 21 | function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) 22 | public 23 | onlyOwner 24 | { 25 | _mintBatch(to, ids, amounts, data); 26 | } 27 | } -------------------------------------------------------------------------------- /contracts/CoinFlip/test/CoinFlip.t.js: -------------------------------------------------------------------------------- 1 | const { assert, expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("CoinFlip", () => { 5 | let CoinFlip; 6 | const val = ethers.parseEther("1"); 7 | const args = "0x6B4c0b11bd7fE1E9e9a69297347cFDccA416dF5F" 8 | 9 | beforeEach(async () => { 10 | CoinFlip = await ethers.deployContract("CoinFlip", [args]); 11 | }) 12 | 13 | describe("flip", async () => { 14 | it("should revert if value is less than entry fees", async () => { 15 | const val = ethers.parseEther("0.1"); 16 | expect(CoinFlip.flip(0, { value: val })).to.be.revertedWith("Insufficient Entry Fund"); 17 | }); 18 | 19 | it("should equal entry fees", async () => { 20 | const entryfees = await CoinFlip.s_entryFees(); 21 | assert.equal(entryfees, val); 22 | }) 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/registrations.md: -------------------------------------------------------------------------------- 1 | # Hacker house registration 2 | 3 | ## Registration 4 | 5 | Add your information to the below list to officially participate in the workshop challenge (This is the first mission of the whole workshop) 6 | 7 | | Emoji | Name | Telegram ID | Github ID | Dorahacks ID | Day 1 | Day 2 | 8 | | ----- | ------------ | ------------- | --------------- | ------------ | ----- | ----- | 9 | | 🧑‍⚖️ | ZxStim | zxstim | zxstim | zxstim | y | | 10 | | 🧑 | SaitamaCoder | @SaitamaCoder | FucktheKingCode | @codepham | y | | 11 | | --- | --- | --- | ------ | --- | --- | --- | 12 | 13 | ⬆️ Submit your registration by adding your information to the table above and open a pull request. After the request is merged, you will get 10 `KLAY` airdrop per day for gas. 14 | -------------------------------------------------------------------------------- /contracts/erc20/tests/MyToken_foundry_test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.13; 3 | 4 | import "forge-std/Test.sol"; 5 | import "../src/ERC20.sol"; 6 | 7 | contract ERC20Test is Test { 8 | MyToken public myTestToken; 9 | 10 | function setUp() public { 11 | myTestToken = new MyToken(address(1)); 12 | } 13 | 14 | function test_TotalSupplyEqualsOwnersBalance() public { 15 | assertEq(myTestToken.totalSupply(), myTestToken.balanceOf(address(1))); 16 | } 17 | 18 | function testTransferBetweenAccounts() public { 19 | vm.prank(address(1)); 20 | myTestToken.transfer(address(2), 500000000000000000000); 21 | assertEq(myTestToken.balanceOf(address(1)), 500000000000000000000); 22 | assertEq(myTestToken.balanceOf(address(2)), 500000000000000000000); 23 | } 24 | 25 | function testFailTransferInsufficientBalance() external { 26 | vm.prank(address(1)); 27 | myTestToken.transfer(address(2), 10000000000000000000000); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Klaytn Foundation 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /workshops/webinar-vietnam-08-05-2024/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 2 | 3 | ## How to 4 | ### Step 1 5 | Go to this repository [https://github.com/klaytn/klaytn-dapp-toolkit](https://github.com/klaytn/klaytn-dapp-toolkit) 6 | 7 | ### Step 2 8 | - Click Fork button on GitHub to fork this repository to your GitHub account 9 | - You can `git clone` to your local folder repository by going to your terminal type or you can click the `.` key on your device to access VS Code online editor. 10 | 11 | ### Step 3 12 | - Copy and paste the content of `Exercise.sol` to Remix IDE. 13 | - Copy and paste the content of `Exercise_test.sol` to Remix IDE inside the `tests` folder 14 | - Edit the content so that the `Exercise.sol` file compiles. 15 | - Run the test. 16 | 17 | ### Step 4 18 | - Copy your newly edited `Exercise.sol` to the `submissions` folder 19 | - Change the name to `Exercise_[github username].sol` matching your GitHub account 20 | - Commit, push and create a Pull Request to the main repo [https://github.com/klaytn/klaytn-dapp-toolkit](https://github.com/klaytn/klaytn-dapp-toolkit) -------------------------------------------------------------------------------- /frontend/wagmi/README.md: -------------------------------------------------------------------------------- 1 | # Wagmi implementations 2 | > A collection of Wagmi v1 and v2 code snippets to help you build your DApp frontend 3 | 4 | ## Wagmi v1 5 | Wagmi is a collection of React Hooks containing everything you need to start working with EVM chains. Wagmi makes it easy to "Connect Wallet," display ENS and balance information, sign messages, interact with contracts, and much more — all with caching, request deduplication, and persistence. 6 | 7 | Full documentation: [https://1.x.wagmi.sh/](https://1.x.wagmi.sh/) 8 | 9 | ## Wagmi v2 10 | Why use Wagmi? Check our their team write up on their [USP](https://wagmi.sh/react/why). Wagmi v2 is a new release so it has not been supported fully by other development tools. 11 | 12 | Full documentation: [https://wagmi.sh/](https://wagmi.sh/) 13 | 14 | ## Klaytn compatible 15 | Both Wagmi v1 and v2 are compatible with Klaytn so you can check out the sample codes included to know how to create `config` for Wagmi to connect to Klaytn DApps. 16 | - [Wagmi v1](/frontend/wagmi/wagmi-v1/README.md) 17 | - [Wagmi v2](/frontend/wagmi/wagmi-v2/README.md) -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from "hardhat/config"; 2 | import "@nomicfoundation/hardhat-toolbox-viem"; 3 | 4 | import "@openzeppelin/hardhat-upgrades"; 5 | 6 | const config: HardhatUserConfig = { 7 | mocha: { 8 | timeout: 0 9 | }, 10 | solidity: { 11 | compilers: [ 12 | { 13 | version: "0.8.24", 14 | settings: { 15 | optimizer: { 16 | enabled: true, 17 | runs: 200, 18 | }, 19 | }, 20 | } 21 | ], 22 | }, 23 | networks: { 24 | hardhat: { 25 | chainId: 31337, 26 | allowUnlimitedContractSize: true 27 | }, 28 | klay: { 29 | url: process.env.KLAY_MAINNET_URL || "", 30 | accounts: 31 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 32 | }, 33 | klayTestnet: { 34 | url: process.env.KLAY_TESTNET_URL || "", 35 | accounts: 36 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 37 | } 38 | } 39 | }; 40 | 41 | export default config; 42 | -------------------------------------------------------------------------------- /contracts/CoinFlip/deploy/deployCoinFlip.s.js: -------------------------------------------------------------------------------- 1 | const { ethers, network } = require("hardhat"); 2 | const { verify } = require("../utils/verify"); 3 | 4 | const deploy = async () => { 5 | 6 | const args = ["0xDA8c0A00A372503aa6EC80f9b29Cc97C454bE499"]; 7 | const sendVal = ethers.parseEther("1.0"); 8 | 9 | const CoinFlip = await ethers.deployContract("CoinFlip", args); 10 | console.log("Deploying contract..."); 11 | await CoinFlip.waitForDeployment(6); 12 | console.log(`Contract Deployed to: ${CoinFlip.target}`) 13 | console.log(network.config) 14 | 15 | // if (network.config.chainId === 1001 && process.env.KLAYTN_RPC) { 16 | // await CoinFlip.waitForDeployment(6); 17 | // await verify(CoinFlip.target, args) 18 | // } else { 19 | // console.log("Contract cannot be verified on Hardhat Network") 20 | // } 21 | 22 | // const flip = await CoinFlip.flip(0, { value: sendVal }); 23 | // await flip.wait(3); 24 | // console.log(`Flipped!`); 25 | } 26 | 27 | deploy().catch((error) => { 28 | console.error(error); 29 | process.exitCode = 1; 30 | }); 31 | -------------------------------------------------------------------------------- /contracts/CoinFlip/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomicfoundation/hardhat-toolbox"); 2 | require("dotenv").config(); 3 | require("@nomicfoundation/hardhat-verify"); 4 | 5 | /** @type import('hardhat/config').HardhatUserConfig */ 6 | const { KLAYTN_RPC, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env || "" 7 | 8 | module.exports = { 9 | solidity: "0.8.19", 10 | defaultNetwork: "hardhat", 11 | networks: { 12 | klaytn: { 13 | url: KLAYTN_RPC || "", 14 | accounts: [PRIVATE_KEY], 15 | chainId: 1001 16 | } 17 | }, 18 | etherscan: { 19 | apiKey: { 20 | klaytn: "unnecessary" 21 | }, 22 | customChains: [ 23 | { 24 | network: "klaytn", 25 | chainId: 1001, 26 | urls: { 27 | apiURL: "https://api-baobab.klaytnscope.com/api", 28 | browserURL: "https://baobab.klaytnscope.com", 29 | }, 30 | }, 31 | ] 32 | }, 33 | sourcify: { 34 | enabled: true 35 | }, 36 | gasReporter: { 37 | enabled: true, 38 | outputFile: "gas-report.txt", 39 | noColors: true 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /contracts/erc3156/deploy/FlashLender.js: -------------------------------------------------------------------------------- 1 | const addresses = { 2 | '1' : { 3 | 'supportedTokens': [ 4 | "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH 5 | "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI 6 | ], 7 | }, 8 | '42' : { 9 | 'supportedTokens': [ 10 | "0xd0A1E359811322d97991E03f863a0C30C2cF029C", // WETH 11 | "0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa", // DAI 12 | ], 13 | } 14 | } 15 | 16 | const func = async function ({ deployments, getNamedAccounts, getChainId }) { 17 | const { deploy, read, execute } = deployments; 18 | const { deployer } = await getNamedAccounts(); 19 | const chainId = await getChainId() 20 | 21 | if (chainId === '31337') { // buidlerevm's chainId 22 | console.log('Local deployments not implemented') 23 | return 24 | } else { 25 | const lender = await deploy('FlashLender', { 26 | from: deployer, 27 | deterministicDeployment: true, 28 | args: [ 29 | addresses[chainId]['supportedTokens'], 30 | 10000, 31 | ], 32 | }) 33 | console.log(`Deployed FlashLender to ${lender.address}`); 34 | } 35 | }; 36 | 37 | module.exports = func; 38 | module.exports.tags = ["FlashLender"]; -------------------------------------------------------------------------------- /contracts/EduChain/test/Lock.js: -------------------------------------------------------------------------------- 1 | const { 2 | time, 3 | loadFixture, 4 | } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); 5 | const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); 6 | const { expect } = require("chai"); 7 | 8 | describe("SchoolSystem", function () { 9 | it("should deploy the SchoolSystem contract and interact with it", async function () { 10 | // Deploy the SchoolSystem contract 11 | const SchoolSystem = await ethers.getContractFactory("SchoolSystem"); 12 | const schoolSystem = await SchoolSystem.deploy("School System", "SCH"); 13 | await schoolSystem.deployed(); 14 | 15 | // Interact with the deployed contract 16 | const [owner, lecturer, student] = await ethers.getSigners(); 17 | 18 | // Employ a lecturer 19 | await schoolSystem.employ_Lecturer(lecturer.address, 100); 20 | 21 | // Admit a student 22 | await schoolSystem.admit_student(student.address, 100); 23 | 24 | // Create a course 25 | const courseName = "Math"; 26 | await schoolSystem.createCourse(courseName, 50); 27 | 28 | // Get all course names 29 | const courses = await schoolSystem.getAllCourseNames(); 30 | 31 | // Verify the behavior 32 | expect(courses).to.deep.include(courseName); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /workshops/webinar-vietnam-08-05-2024/Exercise_test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.4.22 <0.9.0; 4 | 5 | // This import is automatically injected by Remix 6 | import "remix_tests.sol"; 7 | 8 | // This import is required to use custom transaction context 9 | // Although it may fail compilation in 'Solidity Compiler' plugin 10 | // But it will work fine in 'Solidity Unit Testing' plugin 11 | import "remix_accounts.sol"; 12 | import {Counter} from "../Exercise.sol"; 13 | 14 | // File name has to end with '_test.sol', this file can contain more than one testSuite contracts 15 | contract testSuite is Counter { 16 | Counter counter; 17 | 18 | function beforeAll() public { 19 | // 20 | counter = new Counter(); 21 | } 22 | 23 | function checkCount() public returns (bool) { 24 | return Assert.equal(counter.get(), 0, "Count value is not 0"); 25 | } 26 | 27 | function checkIncrement() public returns (bool) { 28 | counter.increment(); 29 | return Assert.equal(counter.get(), 1, "Count value is not 1"); 30 | } 31 | 32 | function checkDecrement() public returns (bool) { 33 | counter.decrement(); 34 | return Assert.equal(counter.get(), 0, "Count value is not 0"); 35 | } 36 | } -------------------------------------------------------------------------------- /contracts/erc5115/test/YearnVault.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import "../src/samples/YearnVaultSY.sol"; 6 | import {Test, console} from "forge-std/Test.sol"; 7 | 8 | contract YearnVaultSYTest is Test { 9 | address _underlying = 0x7CAc58eB7707A83a196D73A4414C665a631Cd585; 10 | address _yvToken = 0x3D63B4766B873F2eEb473ca3545AFda6b0A10BCD; 11 | address myWallet = 0xE41D71FD117236209C25a4C4e67A51d3966B1a84; 12 | 13 | YearnVaultSY yearnVaultSY; 14 | 15 | function setUp() public { 16 | yearnVaultSY = new YearnVaultSY("YearnVaultSY", "YVSY", _underlying, _yvToken); 17 | } 18 | 19 | function testDeposit() public { 20 | hoax(myWallet); 21 | console.log("SY address: ", address(yearnVaultSY)); 22 | _underlying.call(abi.encodeWithSignature("approve(address,uint256)", address(yearnVaultSY), 100)); 23 | vm.prank(myWallet); 24 | console.log("Deposited: ", yearnVaultSY.deposit(myWallet, _underlying, 100, 100)); 25 | } 26 | 27 | function testRedeem() public { 28 | testDeposit(); 29 | hoax(myWallet); 30 | yearnVaultSY.approve(myWallet, 100); 31 | vm.prank(myWallet); 32 | console.log("Redeemed: ", yearnVaultSY.redeem(myWallet, 50, _underlying, 50)); 33 | vm.prank(myWallet); 34 | console.log("Redeemed: ", yearnVaultSY.redeem(myWallet, 50, _yvToken, 50)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/interfaces/IERC3156FlashLender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.0 <0.9.0; 3 | import "./IERC3156FlashBorrower.sol"; 4 | 5 | 6 | interface IERC3156FlashLender { 7 | 8 | /** 9 | * @dev The amount of currency available to be lended. 10 | * @param token The loan currency. 11 | * @return The amount of `token` that can be borrowed. 12 | */ 13 | function maxFlashLoan( 14 | address token 15 | ) external view returns (uint256); 16 | 17 | /** 18 | * @dev The fee to be charged for a given loan. 19 | * @param token The loan currency. 20 | * @param amount The amount of tokens lent. 21 | * @return The amount of `token` to be charged for the loan, on top of the returned principal. 22 | */ 23 | function flashFee( 24 | address token, 25 | uint256 amount 26 | ) external view returns (uint256); 27 | 28 | /** 29 | * @dev Initiate a flash loan. 30 | * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. 31 | * @param token The loan currency. 32 | * @param amount The amount of tokens lent. 33 | * @param data Arbitrary data structure, intended to contain user-defined parameters. 34 | */ 35 | function flashLoan( 36 | IERC3156FlashBorrower receiver, 37 | address token, 38 | uint256 amount, 39 | bytes calldata data 40 | ) external returns (bool); 41 | } -------------------------------------------------------------------------------- /contracts/election/election.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | contract Election { 5 | // Model a Candidate 6 | struct Candidate { 7 | uint256 id; 8 | string name; 9 | uint256 voteCount; 10 | } 11 | 12 | // Store accounts that have voted 13 | mapping(address => bool) public voters; 14 | // Store Candidates 15 | // Fetch Candidate 16 | mapping(uint256 => Candidate) public candidates; 17 | // Store Candidates Count 18 | uint256 public candidatesCount; 19 | 20 | // voted event 21 | event votedEvent(uint256 indexed _candidateId); 22 | 23 | constructor() { 24 | addCandidate("Candidate 1"); 25 | addCandidate("Candidate 2"); 26 | } 27 | 28 | function addCandidate(string memory _name) private { 29 | candidatesCount++; 30 | candidates[candidatesCount] = Candidate(candidatesCount, _name, 0); 31 | } 32 | 33 | function vote(uint256 _candidateId) public { 34 | // require that they haven't voted before 35 | require(!voters[msg.sender]); 36 | 37 | // require a valid candidate 38 | require(_candidateId > 0 && _candidateId <= candidatesCount); 39 | 40 | // record that voter has voted 41 | voters[msg.sender] = true; 42 | 43 | // update candidate vote Count 44 | candidates[_candidateId].voteCount++; 45 | 46 | // trigger voted event 47 | emit votedEvent(_candidateId); 48 | } 49 | } -------------------------------------------------------------------------------- /contracts/erc2981/test/erc1155.test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("ERC1155Example", function () { 5 | 6 | it("Should deploy", async function () { 7 | const Example = await ethers.getContractFactory("ERC1155Example"); 8 | this.example = await Example.deploy(); 9 | await this.example.deployed(); 10 | 11 | // check that the contract indicates it supports royalties 12 | expect(await this.example.supportsInterface("0x2a55205a")).to.equal(true); 13 | }); 14 | 15 | it("Should mint", async function () { 16 | const [owner, wallet] = await ethers.getSigners(); 17 | const tokenId = 420; 18 | const tokenAmount = 1; 19 | 20 | await expect(this.example.mint(wallet.address, tokenId, tokenAmount, "0x", { from: owner.address })) 21 | .to.emit(this.example, 'TransferSingle') 22 | .withArgs(owner.address, ethers.constants.AddressZero, wallet.address, tokenId, tokenAmount); 23 | }); 24 | 25 | it("Check global royalty", async function () { 26 | const [owner] = await ethers.getSigners(); 27 | 28 | // "buy" an NFT for 100 Eth, to make percentage calculation easy 29 | const salePrice = ethers.utils.parseEther("100"); 30 | // get the royalty information from the contract with the sale price 31 | let [reciever, amount] = await this.example.royaltyInfo(420, salePrice); 32 | 33 | // the owner should be getting 5% of the sale 34 | expect(reciever).to.equal(owner.address); 35 | expect(amount).to.equal(ethers.utils.parseEther("5")); 36 | }); 37 | }); -------------------------------------------------------------------------------- /contracts/erc2981/test/erc721.test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers } = require("hardhat"); 3 | 4 | describe("ERC721Example", function () { 5 | let example; 6 | 7 | it("Should deploy", async function () { 8 | const Example = await ethers.getContractFactory("ERC721Example"); 9 | example = await Example.deploy(); 10 | await example.deployed(); 11 | 12 | expect(await example.name()).to.equal("Name"); 13 | expect(await example.symbol()).to.equal("Symbol"); 14 | // check that the contract indicates it supports royalties 15 | expect(await example.supportsInterface("0x2a55205a")).to.equal(true); 16 | }); 17 | 18 | it("Should mint", async function () { 19 | const [_owner, wallet] = await ethers.getSigners(); 20 | const tokenId = 420; 21 | 22 | await expect(example.mint(wallet.address, tokenId)) 23 | .to.emit(example, 'Transfer') 24 | .withArgs(ethers.constants.AddressZero, wallet.address, tokenId); 25 | }); 26 | 27 | it("Check global royalty", async function () { 28 | const [owner] = await ethers.getSigners(); 29 | 30 | // "buy" an NFT for 100 Eth, to make percentage calculation easy 31 | const salePrice = ethers.utils.parseEther("100"); 32 | // get the royalty information from the contract with the sale price 33 | let [reciever, amount] = await example.royaltyInfo(420, salePrice); 34 | 35 | // the owner should be getting 5% of the sale 36 | expect(reciever).to.equal(owner.address); 37 | expect(amount).to.equal(ethers.utils.parseEther("5")); 38 | }); 39 | }); -------------------------------------------------------------------------------- /contracts/erc4626/README.md: -------------------------------------------------------------------------------- 1 | # Motivation 2 | 3 | Let’s say we all own a company, or a liquidity pool, that earns a stablecoin DAI periodically. The stablecoin DAI is the asset in this case. 4 | 5 | One inefficient way we could distribute the earnings is to push out DAI to each of the holders of the company on a pro-rata basis. But this would be extremely expensive gas wise. 6 | 7 | Similarly, if we were to update everyone’s balance inside a smart contract, that would be expensive too. 8 | 9 | Instead, this is how the workflow would work with ERC4626. 10 | 11 | Let’s say you and nine friends get together and each deposit 10 DAI each into the ERC4626 vault (100 DAI total). You get back one share. 12 | 13 | So far so good. Now your company earns 10 more DAI, so the total DAI inside the vault is now 110 DAI. 14 | 15 | When you trade your share back for your part of the DAI, you don’t get 10 DAI back, but 11. 16 | 17 | Now there is 99 DAI in the vault, but 9 people to share it among. If they were to each withdraw, they would get 11 DAI each. 18 | 19 | Note how efficient this is. When someone makes a trade, instead of updating everyones shares one-by-one, only the total supply of shares and the amount of assets in the contract changes. 20 | 21 | ERC4626 does not have to be used in this manner. You can have an arbitrary mathematical formula that determines the relationship between shares and assets. For example, you could say every time someone withdraws the asset, they also have to pay some sort of a tax that depends on the block timestamp or something like that. 22 | 23 | The ERC 4626 standard provides a gas efficient means for executing very common DeFi accounting practices. -------------------------------------------------------------------------------- /contracts/dutch-auction/contracts/DutchAuction.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | interface IERC721 { 5 | function transferFrom(address _from, address _to, uint _nftId) external; 6 | } 7 | 8 | contract DutchAuction { 9 | uint private constant DURATION = 7 days; 10 | 11 | IERC721 public immutable nft; 12 | uint public immutable nftId; 13 | 14 | address payable public immutable seller; 15 | uint public immutable startingPrice; 16 | uint public immutable startAt; 17 | uint public immutable expiresAt; 18 | uint public immutable discountRate; 19 | 20 | constructor(uint _startingPrice, uint _discountRate, address _nft, uint _nftId) { 21 | seller = payable(msg.sender); 22 | startingPrice = _startingPrice; 23 | startAt = block.timestamp; 24 | expiresAt = block.timestamp + DURATION; 25 | discountRate = _discountRate; 26 | 27 | require(_startingPrice >= _discountRate * DURATION, "starting price < min"); 28 | 29 | nft = IERC721(_nft); 30 | nftId = _nftId; 31 | } 32 | 33 | function getPrice() public view returns (uint) { 34 | uint timeElapsed = block.timestamp - startAt; 35 | uint discount = discountRate * timeElapsed; 36 | return startingPrice - discount; 37 | } 38 | 39 | function buy() external payable { 40 | require(block.timestamp < expiresAt, "auction expired"); 41 | 42 | uint price = getPrice(); 43 | require(msg.value >= price, "ETH < price"); 44 | 45 | nft.transferFrom(seller, msg.sender, nftId); 46 | uint refund = msg.value - price; 47 | if (refund > 0) { 48 | payable(msg.sender).transfer(refund); 49 | } 50 | selfdestruct(seller); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/setup-wagmi-v2/README.md: -------------------------------------------------------------------------------- 1 | # Setup Wagmi v2 for React + Vite + TS project 2 | 3 | ## Step 1 4 | Create `config.ts` file in project root directory 5 | ``` 6 | . 7 | ├── config.ts 8 | ├── index.html 9 | ├── node_modules 10 | ├── package.json 11 | ├── pnpm-lock.yaml 12 | ├── public 13 | ├── README.md 14 | ├── src 15 | ├── tsconfig.json 16 | ├── tsconfig.node.json 17 | ├── vite.config.ts 18 | └── yarn.lock 19 | ``` 20 | Add this code snippet (/frontend/wagmi/wagmi-v2/setup-wagmi-v2/react-vite-ts/config.ts) to `config.ts`. 21 | ```tsx 22 | import { http, createConfig } from 'wagmi' 23 | import { klaytn, klaytnBaobab } from 'wagmi/chains' 24 | 25 | // Create wagmiConfig 26 | export const config = createConfig({ 27 | chains: [ klaytn, klaytnBaobab ], 28 | transports: { 29 | [klaytn.id]: http("https://rpc.ankr.com/klaytn"), // you can replace the http() with any other RPC URL you like 30 | [klaytnBaobab.id]: http("https://rpc.ankr.com/klaytn_testnet") // you can replace the http() with any other RPC URL you like 31 | }, 32 | }) 33 | ``` 34 | 35 | 36 | ## Step 2 37 | Wrap your `App` component in `App.tsx` file with the below code snippet 38 | 39 | ```tsx 40 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query' 41 | import { WagmiProvider } from 'wagmi' 42 | import { config } from './config' 43 | 44 | const queryClient = new QueryClient() 45 | 46 | function App() { 47 | return ( 48 | 49 | 50 | {/** ... */} 51 | 52 | 53 | ) 54 | } 55 | ``` 56 | 57 | ## Resources 58 | - [`config.ts`](/frontend/wagmi/wagmi-v2/setup-wagmi-v2/react-vite-ts/config.ts) 59 | - [`App.tsx`](/frontend/wagmi/wagmi-v2/setup-wagmi-v2/react-vite-ts/App.tsx) -------------------------------------------------------------------------------- /contracts/erc5115/src/libraries/TokenHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 6 | 7 | abstract contract TokenHelper { 8 | using SafeERC20 for IERC20; 9 | 10 | address internal constant NATIVE = address(0); 11 | 12 | function _transferIn(address token, address from, uint256 amount) internal { 13 | if (token == NATIVE) return; 14 | IERC20(token).safeTransferFrom(from, address(this), amount); 15 | } 16 | 17 | function _transferOut(address token, address to, uint256 amount) internal { 18 | if (token == NATIVE) { 19 | (bool success,) = to.call{value: amount}(""); 20 | require(success, "eth send failed"); 21 | } else { 22 | IERC20(token).safeTransfer(to, amount); 23 | } 24 | } 25 | 26 | function _selfBalance(address token) internal view returns (uint256) { 27 | return (token == NATIVE) ? address(this).balance : IERC20(token).balanceOf(address(this)); 28 | } 29 | 30 | /// @notice Approves the stipulated contract to spend the given allowance in the given token 31 | /// @dev Errors with 'SA' if transfer fails 32 | /// @param token The contract address of the token to be approved 33 | /// @param to The target of the approval 34 | /// @param value The amount of the given token the target will be allowed to spend 35 | function _safeApprove(address token, address to, uint256 value) internal { 36 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); 37 | require(success && (data.length == 0 || abi.decode(data, (bool))), "Safe Approve"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/EduChain/contracts/FactorySchool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.7; 3 | 4 | import "./School.sol"; // Import the SchoolSystem contract 5 | 6 | contract SchoolSystemFactory { 7 | address[] internal deployedSchoolSystems; // Store addresses of deployed SchoolSystem contracts 8 | mapping(address => address) internal schoolOwners; // Map school owner to school address 9 | mapping(address => address[]) internal schoolsByOwner; // Map owner address to array of school addresses 10 | 11 | // Event emitted when a new SchoolSystem contract is deployed 12 | event SchoolSystemDeployed(address indexed schoolSystem, address indexed owner); 13 | 14 | // Function to deploy a new SchoolSystem contract 15 | function createSchoolSystem(string memory name, string memory symbol) external { 16 | SchoolSystem newSchoolSystem = new SchoolSystem(name, symbol); // Deploy a new instance of SchoolSystem 17 | address newSchoolAddress = address(newSchoolSystem); 18 | deployedSchoolSystems.push(newSchoolAddress); // Store the address of the deployed contract 19 | schoolOwners[newSchoolAddress] = msg.sender; // Store the owner of the school 20 | schoolsByOwner[msg.sender].push(newSchoolAddress); // Store the school address under the owner's list 21 | emit SchoolSystemDeployed(newSchoolAddress, msg.sender); // Emit an event 22 | } 23 | 24 | 25 | // Function to get the number of deployed SchoolSystem contracts 26 | function getDeployedSchoolSystemsCount() external view returns (uint) { 27 | return deployedSchoolSystems.length; 28 | } 29 | 30 | // Function to return all schools created by an address 31 | function getSchoolsByOwner(address owner) external view returns (address[] memory) { 32 | return schoolsByOwner[owner]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/erc4626/tests/MyVault_foundry_test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | 3 | pragma solidity ^0.8.20; 4 | 5 | import { MyVault } from "../contracts/MyVault.sol"; 6 | import { MyToken } from "../contracts/MyToken.sol"; 7 | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 9 | import { console, Test } from "forge-std/Test.sol"; 10 | 11 | contract ERC4626Test is Test { 12 | MyVault vault; 13 | MyToken myToken; 14 | 15 | function setUp() public { 16 | console.log("address this: ", address(this)); 17 | myToken = new MyToken(address(this)); 18 | vault = new MyVault(address(myToken)); 19 | } 20 | 21 | function testDeposit() public returns (uint256) { 22 | uint256 depositAmount = myToken.balanceOf(address(this)); 23 | myToken.approve(address(vault), depositAmount); 24 | vault.deposit(depositAmount, address(this)); 25 | assertEq(myToken.balanceOf(address(this)), 0); 26 | assertEq(vault.balanceOf(address(this)), depositAmount); 27 | return depositAmount; 28 | } 29 | 30 | function testWithdraw() public { 31 | uint256 depositAmount = testDeposit(); 32 | uint256 withdrawAmount = depositAmount; 33 | vault.withdraw(withdrawAmount, address(this), address(this)); 34 | assertEq(myToken.balanceOf(address(this)), withdrawAmount); 35 | assertEq(vault.balanceOf(address(this)), 0); 36 | } 37 | 38 | function testRedeem() public { 39 | uint256 depositAmount = testDeposit(); 40 | uint256 currentShare = vault.balanceOf(address(this)); 41 | uint256 redeemAmount = currentShare / 2; 42 | vault.redeem(redeemAmount, address(this), address(this)); 43 | assertEq(vault.balanceOf(address(this)), currentShare - redeemAmount); 44 | console.log(myToken.balanceOf(address(this))); 45 | } 46 | } -------------------------------------------------------------------------------- /frontend/wagmi/wagmi-v2/connect-wallet/web3modal/react-vite-ts/context/index.tsx: -------------------------------------------------------------------------------- 1 | import { createWeb3Modal } from '@web3modal/wagmi/react' 2 | 3 | import { http, createConfig, WagmiProvider } from 'wagmi' 4 | import { klaytn, klaytnBaobab } from 'wagmi/chains' 5 | import { walletConnect, injected, coinbaseWallet } from 'wagmi/connectors' 6 | 7 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query' 8 | 9 | // 0. Setup queryClient 10 | const queryClient = new QueryClient() 11 | 12 | // 1. Get projectId at https://cloud.walletconnect.com 13 | const projectId = 'YOUR_PROJECT_ID' 14 | 15 | // 2. Create WallectConnect config 16 | const metadata = { 17 | name: 'Web3Modal', // add name of your DApp 18 | description: 'Web3Modal Example', // add description of your DApp 19 | url: 'https://web3modal.com', // origin must match your domain & subdomain 20 | icons: ['https://avatars.githubusercontent.com/u/37784886'] 21 | } 22 | 23 | // Create wagmiConfig 24 | const config = createConfig({ 25 | chains: [ klaytn, klaytnBaobab ], 26 | transports: { 27 | [klaytn.id]: http("https://rpc.ankr.com/klaytn"), // you can replace the http() with any other RPC URL you like 28 | [klaytnBaobab.id]: http("https://rpc.ankr.com/klaytn_testnet") // you can replace the http() with any other RPC URL you like 29 | }, 30 | connectors: [ 31 | walletConnect({ projectId, metadata, showQrModal: false }), 32 | injected({ shimDisconnect: true }), 33 | ] 34 | }) 35 | 36 | // 3. Create Web3Modal 37 | createWeb3Modal({ 38 | wagmiConfig: config, 39 | projectId, 40 | enableAnalytics: false, // Optional - defaults to your Cloud configuration 41 | defaultChain: klaytn, klaytnBaobab, 42 | chainImages: { 43 | 8217: '/Klaytn_Symbol.png', 44 | 1001: '/Klaytn_Symbol.png' 45 | } 46 | }) 47 | 48 | 49 | export function Web3Modal({ children }) { 50 | return ( 51 | 52 | {children} 53 | 54 | ) 55 | } -------------------------------------------------------------------------------- /contracts/erc20/tests/MyToken_remix_test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | 3 | pragma solidity >=0.7.0 <0.9.0; 4 | import "remix_tests.sol"; // this import is automatically injected by Remix. 5 | import "remix_accounts.sol"; 6 | import "hardhat/console.sol"; 7 | import "../contracts/erc20.sol"; 8 | 9 | 10 | contract ERC20Test is MyToken(TestsAccounts.getAccount(0)) { 11 | /// Define variables referring to different accounts 12 | address acc0; 13 | address acc1; 14 | address acc2; 15 | 16 | MyToken myTokenToTest; 17 | 18 | function beforeAll () public { 19 | acc0 = TestsAccounts.getAccount(0); 20 | acc1 = TestsAccounts.getAccount(1); 21 | acc2 = TestsAccounts.getAccount(2); 22 | 23 | myTokenToTest = new MyToken(acc0); 24 | } 25 | 26 | function checkTotalSupplyEqualsOwnerBalance () public { 27 | console.log("Checking total supply of tokens assigned to the owner"); 28 | Assert.equal(totalSupply(), uint(balanceOf(acc0)), "totalsupply should equals balance of user"); 29 | } 30 | 31 | 32 | function checkTransferBetweenAccounts () public { 33 | console.log("Checking transfer tokens between accounts"); 34 | Assert.ok(msg.sender == acc0, 'caller should be default account i.e. acc0'); 35 | transfer(acc1, 500000000000000000000); 36 | Assert.equal(uint(balanceOf(acc0)), (500000000000000000000), "Should transfer between account: sender value reduced"); 37 | Assert.equal(uint(balanceOf(acc1)), uint(500000000000000000000), "Should transfer between account: recipient value increased"); 38 | } 39 | 40 | function checkTransferFailedForIsInsufficientBal () public { 41 | console.log("Checking failure if sender doesn't have enough tokens"); 42 | Assert.ok(msg.sender == acc0, 'caller should be acc0'); 43 | 44 | bytes memory methodSign = abi.encodeWithSignature('transfer(address,uint256)', acc2, 200000000000000000000000); 45 | (bool success,) = address(myTokenToTest).call(methodSign); 46 | // 'success' will be false if method execution is not successful 47 | Assert.equal(success, false, 'execution should be successful'); 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /contracts/ContriBoost/contracts/FactoryContribute.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@klaytn/contracts/token/ERC20/IERC20.sol"; 5 | import "./Contribute.sol"; 6 | 7 | 8 | contract ContributionSystemFactory { 9 | // Structure to store system information 10 | struct SystemInfo { 11 | address systemAddress; // Address of the ContributionSystem contract 12 | address creator; // Address of the creator 13 | } 14 | 15 | mapping(address => SystemInfo[]) public systemsByCreator; // Mapping of the creator's address to their ContributionSystem contracts 16 | address[] public deployedSystems; // Array to store addresses of all deployed ContributionSystem contracts 17 | 18 | event ContributionSystemCreated(address indexed newSystem, address indexed creator); 19 | 20 | // Create a new instance of the ContributionSystem contract 21 | function createContributionSystem( 22 | address coordinator, 23 | bytes32 _keyHash, 24 | uint256 _fee, 25 | uint _dayRange, 26 | uint _expectedNumber, 27 | uint _contributionAmount, 28 | address _tokenAddress 29 | ) external { 30 | ContributionSystem newSystem = new ContributionSystem( 31 | coordinator, 32 | _keyHash, 33 | _fee, 34 | _dayRange, 35 | _expectedNumber, 36 | _contributionAmount, 37 | _tokenAddress 38 | ); 39 | deployedSystems.push(address(newSystem)); 40 | emit ContributionSystemCreated(address(newSystem), msg.sender); 41 | 42 | SystemInfo memory info; 43 | info.systemAddress = address(newSystem); 44 | info.creator = msg.sender; 45 | systemsByCreator[msg.sender].push(info); 46 | } 47 | 48 | // Returns the list of deployed ContributionSystem contracts 49 | function getDeployedSystems() external view returns (address[] memory) { 50 | return deployedSystems; 51 | } 52 | 53 | // Returns the list of ContributionSystem contracts deployed by a specific creator 54 | function getSystemsByCreator(address _creator) external view returns (SystemInfo[] memory) { 55 | return systemsByCreator[_creator]; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/erc20/README.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | ## ERC20 smart contract 4 | 1. 5 | 6 | ## Remix 7 | 1. Copy and paste the `MyToken.sol` file into the `contracts` folder on Remix 8 | 2. Copy and paste the MyToken_remix_test.sol file into `test` folder 9 | 3. Compile and run test 10 | 4. Deploy using Remix `Deploy` tab 11 | 12 | ## Hardhat 13 | 1. Follow Hardhat documentation to set up your project 14 | > It is highly recommended that you set up your project with Typescript 15 | 16 | Project structure 17 | ```bash 18 | project-repo 19 | ├── contracts/ 20 | ├── scripts/ 21 | ├── test/ 22 | └── hardhat.config.js 23 | ``` 24 | 25 | 2. Copy and paste the `MyToken.sol` file into the `contracts` folder 26 | 3. Copy and paste the MyToken_hardhat_test.ts file into the `test` folder 27 | 4. Copy the content of the `hardhat.config.js` file below and set your vars (refer to [Hardhat Managing Configuration variables](https://hardhat.org/hardhat-runner/docs/guides/configuration-variables#managing-configuration-variables)) 28 | ```js 29 | import { HardhatUserConfig } from "hardhat/config"; 30 | const { vars } = require("hardhat/config"); 31 | import "@nomicfoundation/hardhat-toolbox"; 32 | 33 | const config: HardhatUserConfig = { 34 | defaultNetwork: "cypress", 35 | networks: { 36 | hardhat: { 37 | }, 38 | // klaytn mainnet 39 | cypress: { 40 | url: "https://rpc.ankr.com/klaytn", 41 | chainId: 8217, 42 | gas: "auto", 43 | gasPrice: "auto", 44 | gasMultiplier: 1, 45 | accounts: [vars.get("PRIVATE_KEY")] 46 | }, 47 | // klaytn testnet 48 | baobab: { 49 | url: "https://rpc.ankr.com/klaytn_testnet", 50 | chainId: 1001, 51 | gas: "auto", 52 | gasPrice: "auto", 53 | gasMultiplier: 1, 54 | accounts: [vars.get("PRIVATE_KEY")] 55 | } 56 | }, 57 | solidity: { 58 | version: "0.8.23", 59 | settings: { 60 | optimizer: { 61 | enabled: true, 62 | runs: 200 63 | } 64 | } 65 | }, 66 | }; 67 | 68 | export default config; 69 | ``` 70 | 5. Follow Hardhat documentation on [Deployment](https://hardhat.org/hardhat-runner/docs/guides/deploying) to deploy your contract to Baobab (testnet) or Cypress (mainnet). 71 | 72 | ## Foundry 73 | 1. Follow Foundry documentation to set up your project 74 | 75 | Project structure 76 | ```bash 77 | project-repo 78 | ├── README.md 79 | ├── foundry.toml 80 | ├── lib 81 | ├── script 82 | ├── src 83 | └── test 84 | ``` 85 | 2. -------------------------------------------------------------------------------- /contracts/english-auction/contracts/EnglishAuction.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | interface IERC721 { 5 | function safeTransferFrom(address from, address to, uint tokenId) external; 6 | 7 | function transferFrom(address, address, uint) external; 8 | } 9 | 10 | contract EnglishAuction { 11 | event Start(); 12 | event Bid(address indexed sender, uint amount); 13 | event Withdraw(address indexed bidder, uint amount); 14 | event End(address winner, uint amount); 15 | 16 | IERC721 public nft; 17 | uint public nftId; 18 | 19 | address payable public seller; 20 | uint public endAt; 21 | bool public started; 22 | bool public ended; 23 | 24 | address public highestBidder; 25 | uint public highestBid; 26 | mapping(address => uint) public bids; 27 | 28 | constructor(address _nft, uint _nftId, uint _startingBid) { 29 | nft = IERC721(_nft); 30 | nftId = _nftId; 31 | 32 | seller = payable(msg.sender); 33 | highestBid = _startingBid; 34 | } 35 | 36 | function start() external { 37 | require(!started, "started"); 38 | require(msg.sender == seller, "not seller"); 39 | 40 | nft.transferFrom(msg.sender, address(this), nftId); 41 | started = true; 42 | endAt = block.timestamp + 7 days; 43 | 44 | emit Start(); 45 | } 46 | 47 | function bid() external payable { 48 | require(started, "not started"); 49 | require(block.timestamp < endAt, "ended"); 50 | require(msg.value > highestBid, "value < highest"); 51 | 52 | if (highestBidder != address(0)) { 53 | bids[highestBidder] += highestBid; 54 | } 55 | 56 | highestBidder = msg.sender; 57 | highestBid = msg.value; 58 | 59 | emit Bid(msg.sender, msg.value); 60 | } 61 | 62 | function withdraw() external { 63 | uint bal = bids[msg.sender]; 64 | bids[msg.sender] = 0; 65 | payable(msg.sender).transfer(bal); 66 | 67 | emit Withdraw(msg.sender, bal); 68 | } 69 | 70 | function end() external { 71 | require(started, "not started"); 72 | require(block.timestamp >= endAt, "not ended"); 73 | require(!ended, "ended"); 74 | 75 | ended = true; 76 | if (highestBidder != address(0)) { 77 | nft.safeTransferFrom(address(this), highestBidder, nftId); 78 | seller.transfer(highestBid); 79 | } else { 80 | nft.safeTransferFrom(address(this), seller, nftId); 81 | } 82 | 83 | emit End(highestBidder, highestBid); 84 | } 85 | } -------------------------------------------------------------------------------- /contracts/erc3156/contracts/FlashBorrower.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "./interfaces/IERC20.sol"; 5 | import "./interfaces/IERC3156FlashBorrower.sol"; 6 | import "./interfaces/IERC3156FlashLender.sol"; 7 | 8 | 9 | contract FlashBorrower is IERC3156FlashBorrower { 10 | enum Action {NORMAL, STEAL, REENTER} 11 | 12 | IERC3156FlashLender lender; 13 | 14 | uint256 public flashBalance; 15 | address public flashInitiator; 16 | address public flashToken; 17 | uint256 public flashAmount; 18 | uint256 public flashFee; 19 | 20 | constructor (IERC3156FlashLender lender_) { 21 | lender = lender_; 22 | } 23 | 24 | /// @dev ERC-3156 Flash loan callback 25 | function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external override returns(bytes32) { 26 | require(msg.sender == address(lender), "FlashBorrower: Untrusted lender"); 27 | require(initiator == address(this), "FlashBorrower: External loan initiator"); 28 | (Action action) = abi.decode(data, (Action)); // Use this to unpack arbitrary data 29 | flashInitiator = initiator; 30 | flashToken = token; 31 | flashAmount = amount; 32 | flashFee = fee; 33 | if (action == Action.NORMAL) { 34 | flashBalance = IERC20(token).balanceOf(address(this)); 35 | } else if (action == Action.STEAL) { 36 | // do nothing 37 | } else if (action == Action.REENTER) { 38 | flashBorrow(token, amount * 2); 39 | } 40 | return keccak256("ERC3156FlashBorrower.onFlashLoan"); 41 | } 42 | 43 | function flashBorrow(address token, uint256 amount) public { 44 | // Use this to pack arbitrary data to `onFlashLoan` 45 | bytes memory data = abi.encode(Action.NORMAL); 46 | approveRepayment(token, amount); 47 | lender.flashLoan(this, token, amount, data); 48 | } 49 | 50 | function flashBorrowAndSteal(address token, uint256 amount) public { 51 | // Use this to pack arbitrary data to `onFlashLoan` 52 | bytes memory data = abi.encode(Action.STEAL); 53 | lender.flashLoan(this, token, amount, data); 54 | } 55 | 56 | function flashBorrowAndReenter(address token, uint256 amount) public { 57 | // Use this to pack arbitrary data to `onFlashLoan` 58 | bytes memory data = abi.encode(Action.REENTER); 59 | approveRepayment(token, amount); 60 | lender.flashLoan(this, token, amount, data); 61 | } 62 | 63 | function approveRepayment(address token, uint256 amount) public { 64 | uint256 _allowance = IERC20(token).allowance(address(this), address(lender)); 65 | uint256 _fee = lender.flashFee(token, amount); 66 | uint256 _repayment = amount + _fee; 67 | IERC20(token).approve(address(lender), _allowance + _repayment); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.7.0 || ^0.8.0; 4 | 5 | /** 6 | * @dev Interface of the ERC20 standard as defined in the EIP. 7 | */ 8 | interface IERC20 { 9 | /** 10 | * @dev Returns the amount of tokens in existence. 11 | */ 12 | function totalSupply() external view returns (uint256); 13 | 14 | /** 15 | * @dev Returns the amount of tokens owned by `account`. 16 | */ 17 | function balanceOf(address account) external view returns (uint256); 18 | 19 | /** 20 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 21 | * 22 | * Returns a boolean value indicating whether the operation succeeded. 23 | * 24 | * Emits a {Transfer} event. 25 | */ 26 | function transfer(address recipient, uint256 amount) external returns (bool); 27 | 28 | /** 29 | * @dev Returns the remaining number of tokens that `spender` will be 30 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 31 | * zero by default. 32 | * 33 | * This value changes when {approve} or {transferFrom} are called. 34 | */ 35 | function allowance(address owner, address spender) external view returns (uint256); 36 | 37 | /** 38 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 39 | * 40 | * Returns a boolean value indicating whether the operation succeeded. 41 | * 42 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 43 | * that someone may use both the old and the new allowance by unfortunate 44 | * transaction ordering. One possible solution to mitigate this race 45 | * condition is to first reduce the spender's allowance to 0 and set the 46 | * desired value afterwards: 47 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 48 | * 49 | * Emits an {Approval} event. 50 | */ 51 | function approve(address spender, uint256 amount) external returns (bool); 52 | 53 | /** 54 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 55 | * allowance mechanism. `amount` is then deducted from the caller's 56 | * allowance. 57 | * 58 | * Returns a boolean value indicating whether the operation succeeded. 59 | * 60 | * Emits a {Transfer} event. 61 | */ 62 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 63 | 64 | /** 65 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 66 | * another (`to`). 67 | * 68 | * Note that `value` may be zero. 69 | */ 70 | event Transfer(address indexed from, address indexed to, uint256 value); 71 | 72 | /** 73 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 74 | * a call to {approve}. `value` is the new allowance. 75 | */ 76 | event Approval(address indexed owner, address indexed spender, uint256 value); 77 | } -------------------------------------------------------------------------------- /contracts/EduChain/README.md: -------------------------------------------------------------------------------- 1 | # SchoolSystemFactory and SchoolContract Explanation 2 | 3 | ## SchoolSystemFactory Contract 4 | 5 | ### Overview: 6 | - The `SchoolSystemFactory` contract is responsible for deploying instances of the `SchoolSystem` contract. 7 | - It keeps track of deployed `SchoolSystem` contracts by storing their addresses in the `deployedSchoolSystems` array. 8 | 9 | ### Functions: 10 | 1. **`createSchoolSystem`**: 11 | - Function to deploy a new instance of the `SchoolSystem` contract. 12 | - Accepts parameters `name` and `symbol` for the name and symbol of the associated KIP17 token. 13 | - Emits an event `SchoolSystemDeployed` after deployment. 14 | 15 | 2. **`getDeployedSchoolSystemsCount`**: 16 | - View function to get the number of deployed `SchoolSystem` contracts. 17 | - Returns the length of the `deployedSchoolSystems` array. 18 | 19 | ## SchoolSystem Contract 20 | 21 | ### Overview: 22 | - The `SchoolSystem` contract represents a system for managing courses, students, and lecturers in a school. 23 | - It inherits from the `KIP17` contract, allowing it to act as a Klaytn-based non-fungible token (NFT). 24 | - The contract also uses the `Ownable` contract, enabling ownership management functionalities. 25 | 26 | ### Storage Variables: 27 | - `courseCount`, `lecturerCount`, and `studentCount`: Counters for tracking the number of courses, lecturers, and students. 28 | - Various mappings for storing course details, lecturer and student tokens, and attendance information. 29 | 30 | ### Modifiers: 31 | - `onlyAdmin`, `onlyLecturer`, and `onlyStudent`: Modifiers restricting access to certain functions based on roles. 32 | 33 | ### Constructor: 34 | - Initializes the contract with the name and symbol of the associated KIP17 token. 35 | 36 | ### Functions: 37 | 1. **Management Functions**: 38 | - `employ_Lecturer`: Employ a new lecturer. 39 | - `admit_student`: Admit a new student. 40 | - `transferOwnership`: Transfer ownership of the contract. 41 | 42 | 2. **Course Management Functions**: 43 | - `createCourse`: Create a new course. 44 | - `registerForCourse`: Register a student for a course. 45 | 46 | 3. **Class Session Functions**: 47 | - `createClassSession`: Create a new class session for a course. 48 | - `markAttendance`: Mark attendance for a class session. 49 | 50 | 4. **Query Functions**: 51 | - `getSessionIdsForLecturer`: Get session IDs for a lecturer. 52 | - `getTotalRegisteredCourses`: Get the total number of registered courses for a student. 53 | - `calculateAttendancePercentage`: Calculate the attendance percentage for a student. 54 | 55 | ### Internal Functions: 56 | - `courseNameExists`: Check if a course name already exists. 57 | - `getCourseSessionIds`: Get session IDs for a specific course. 58 | 59 | ### Events: 60 | - `StudentRegistered`: Fired when a student registers for a course. 61 | - `CourseCreated`: Fired when a new course is created. 62 | - `ClassSessionCreated`: Fired when a new class session is created. 63 | - `AttendanceMarked`: Fired when attendance is marked for a class session. 64 | -------------------------------------------------------------------------------- /contracts/soulbound-nft/contracts/SoulboundNFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 6 | import "@openzeppelin/contracts/access/Ownable.sol"; 7 | import "@openzeppelin/contracts/security/Pausable.sol"; 8 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; 9 | 10 | /** 11 | * @title Soulbound NFT 12 | * @author Breakthrough-Labs Inc. 13 | * @notice NFT, Soulbound, ERC721 14 | * @custom:version 1.0.10 15 | * @custom:address 1285485 16 | * @custom:default-precision 0 17 | * @custom:simple-description Soulbound NFT with owner minting. 18 | * @dev ERC721 Soulbound NFT with the following features: 19 | * 20 | * - Deployer can mint to recipients. 21 | * - No transfer capability. 22 | * 23 | */ 24 | 25 | contract SoulboundNFT is ERC721, ERC721Enumerable, Pausable, Ownable { 26 | string private _baseURIextended; 27 | uint256 public immutable MAX_SUPPLY; 28 | 29 | /** 30 | * @param _name NFT Name 31 | * @param _symbol NFT Symbol 32 | * @param _uri Token URI used for metadata 33 | * @param maxSupply Maximum # of NFTs 34 | */ 35 | constructor( 36 | string memory _name, 37 | string memory _symbol, 38 | string memory _uri, 39 | uint256 maxSupply 40 | ) payable ERC721(_name, _symbol) { 41 | _baseURIextended = _uri; 42 | MAX_SUPPLY = maxSupply; 43 | pause(); 44 | } 45 | 46 | /** 47 | * @dev Pauses the NFT, preventing any transfers. Called by default on a SBT. 48 | */ 49 | function pause() internal { 50 | _pause(); 51 | } 52 | 53 | /** 54 | * @dev An external method for the owner to mint Soulbound NFTs. Requires that the minted NFTs will not exceed the `MAX_SUPPLY`. 55 | */ 56 | function mint(address to) external onlyOwner{ 57 | uint256 ts = totalSupply(); 58 | require(ts + 1 <= MAX_SUPPLY, "Mint would exceed max supply"); 59 | _safeMint(to, ts); 60 | } 61 | 62 | /** 63 | * @dev Updates the baseURI that will be used to retrieve NFT metadata. 64 | * @param baseURI_ The baseURI to be used. 65 | */ 66 | function setBaseURI(string memory baseURI_) external onlyOwner { 67 | _baseURIextended = baseURI_; 68 | } 69 | 70 | // Required Overrides 71 | 72 | function _baseURI() internal view virtual override returns (string memory) { 73 | return _baseURIextended; 74 | } 75 | 76 | function _beforeTokenTransfer( 77 | address from, 78 | address to, 79 | uint256 tokenId 80 | ) internal override(ERC721, ERC721Enumerable) { 81 | require(_msgSender() == owner() && paused(), "not owner cannot mint"); 82 | super._beforeTokenTransfer(from, to, tokenId); 83 | } 84 | 85 | function supportsInterface(bytes4 interfaceId) 86 | public 87 | view 88 | override(ERC721, ERC721Enumerable) 89 | returns (bool) 90 | { 91 | return super.supportsInterface(interfaceId); 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /contracts/erc5115/src/abstracts/SYBaseWithRewards.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "../interfaces/IStandardizedYield.sol"; 5 | import "./RewardManager.sol"; 6 | import "./SYBase.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | 9 | abstract contract SCYBaseWithRewards is SYBase, RewardManager { 10 | using Math for uint256; 11 | 12 | constructor(string memory _name, string memory _symbol, address _yieldToken) SYBase(_name, _symbol, yieldToken) {} 13 | 14 | /*/////////////////////////////////////////////////////////////// 15 | REWARDS-RELATED 16 | //////////////////////////////////////////////////////////////*/ 17 | 18 | /** 19 | * @dev See {IStandardizedYield-claimRewards} 20 | */ 21 | function claimRewards(address user) external virtual override returns (uint256[] memory rewardAmounts) { 22 | _updateAndDistributeReward(user); 23 | rewardAmounts = _doTransferOutRewards(user, user); 24 | 25 | emit ClaimRewards(user, _getRewardTokens(), rewardAmounts); 26 | } 27 | 28 | /** 29 | * @dev See {IStandardizedYield-getRewardTokens} 30 | */ 31 | function getRewardTokens() external view virtual override returns (address[] memory rewardTokens) { 32 | rewardTokens = _getRewardTokens(); 33 | } 34 | 35 | /** 36 | * @dev See {IStandardizedYield-accruedRewards} 37 | */ 38 | function accruedRewards(address user) external view virtual override returns (uint256[] memory rewardAmounts) { 39 | address[] memory rewardTokens = _getRewardTokens(); 40 | rewardAmounts = new uint256[](rewardTokens.length); 41 | for (uint256 i = 0; i < rewardTokens.length;) { 42 | rewardAmounts[i] = userRewardAccrued[user][rewardTokens[i]]; 43 | unchecked { 44 | i++; 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * @notice returns the total number of reward shares 51 | * @dev this is simply the total supply of shares, as rewards shares are equivalent to SCY shares 52 | */ 53 | function _rewardSharesTotal() internal virtual override returns (uint256) { 54 | return totalSupply(); 55 | } 56 | 57 | /** 58 | * @notice returns the reward shares of (`user`) 59 | * @dev this is simply the SCY balance of (`user`), as rewards shares are equivalent to SCY shares 60 | */ 61 | function _rewardSharesUser(address user) internal virtual override returns (uint256) { 62 | return balanceOf(user); 63 | } 64 | 65 | /*/////////////////////////////////////////////////////////////// 66 | TRANSFER HOOKS 67 | //////////////////////////////////////////////////////////////*/ 68 | function _beforeTokenTransfer(address from, address to, uint256 /*amount*/ ) internal virtual { 69 | _updateRewardIndex(); 70 | if (from != address(0) && from != address(this)) _distributeUserReward(from); 71 | if (to != address(0) && to != address(this)) _distributeUserReward(to); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/README.md: -------------------------------------------------------------------------------- 1 | # Hacker house rules 2 | 3 | ## General information 4 | 1. Make sure to sign up in the [`registrations.md`](/klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/registrations.md) 5 | 2. To be eligible for bounty rewards, you have to have a corresponding Pull Request/Issue that is explicitly approved by an administrator. 6 | 3. Some Pull Request/Issue might take longer to be approved/merged due to a subjective reason will be communicated to you. 7 | 8 | ## Additional tracks 9 | 10 | ### SDK 11 | Contribute an SDK using API of Klaytn ecosystem projects 12 | 13 | #### Rewards 14 | - 100 - 500 KLAY per `merged` PR/submission 15 | 16 | #### Details 17 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 18 | - Rewards are based on complexity and quality of end result 19 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 20 | 21 | #### Ideas 22 | - OKLink SDK (js/ts and python) 23 | - DEX SDK (js/ts and python) 24 | 25 | #### Submission rules 26 | - Open source 27 | - Bounty submission should be of good quality (well tested for core functionalities) 28 | 29 | --- 30 | 31 | ### Education 32 | 33 | Contribute to education materials on klaytn 34 | 35 | #### Rewards 36 | - 20 - 100 KLAY per `merged` PR/submission 37 | 38 | #### Details 39 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 40 | 41 | #### Ideas 42 | - Improved tutorials from [Klaytn examples](https://github.com/klaytn/examples) 43 | - An information page on [DeFi.vn](https://defi.vn) 44 | 45 | #### Rules 46 | - Open source 47 | - Bounty submission should be of good quality (well tested for core functionalities) 48 | 49 | --- 50 | 51 | ### Contribute a Telegram Bot to perform some actions on Klaytn 52 | 53 | Contribute a telegram bot 54 | 55 | #### Rewards 56 | - 500 KLAY per `merged` PR/submission 57 | 58 | #### Details 59 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 60 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 61 | - Can be forks 62 | 63 | #### Ideas 64 | - Telegram bot to check wallet balance 65 | - Telegram bot to manage and distribute NFTs 66 | - Telegram bot to trade on klaytn DEXes 67 | - Telegram bot to launch mint.club coins 68 | 69 | #### Rules 70 | - Open source 71 | - Bounty submission should be of good quality (well tested for core functionalities) 72 | 73 | --- 74 | 75 | ### Contribute a cool NFT implementation/forks on Klaytn 76 | 77 | #### Rewards 78 | - 100 - 800 KLAY per `merged` PR/submission 79 | 80 | #### Details 81 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 82 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 83 | - Can be forks 84 | 85 | #### Ideas 86 | - Nouns fork 87 | - DN404 tokens (hybrid NFT) 88 | - ERC6551 89 | 90 | #### Rules 91 | - Open source 92 | - Bounty submission should be of good quality (well tested for core functionalities) 93 | 94 | -------------------------------------------------------------------------------- /klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/rules.md: -------------------------------------------------------------------------------- 1 | # Hacker house rules 2 | 3 | ## General information 4 | 1. Make sure to sign up in the [`registrations.md`](/klaytn-hacker-house/on-site-sessions/gmvietnam-hackerhouse/registrations.md) 5 | 2. To be eligible for bounty rewards, you have to have a corresponding Pull Request/Issue that is explicitly approved by an administrator. 6 | 3. Some Pull Request/Issue might take longer to be approved/merged due to a subjective reason will be communicated to you. 7 | 8 | ## Additional tracks 9 | 10 | ### SDK 11 | Contribute an SDK using API of Klaytn ecosystem projects 12 | 13 | #### Rewards 14 | - 100 - 500 KLAY per `merged` PR/submission 15 | 16 | #### Details 17 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 18 | - Rewards are based on complexity and quality of end result 19 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 20 | 21 | #### Ideas 22 | - OKLink SDK (js/ts and python) 23 | - DEX SDK (js/ts and python) 24 | 25 | #### Submission rules 26 | - Open source 27 | - Bounty submission should be of good quality (well tested for core functionalities) 28 | 29 | --- 30 | 31 | ### Education 32 | 33 | Contribute to education materials on klaytn 34 | 35 | #### Rewards 36 | - 20 - 100 KLAY per `merged` PR/submission 37 | 38 | #### Details 39 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 40 | 41 | #### Ideas 42 | - Improved tutorials from [Klaytn examples](https://github.com/klaytn/examples) 43 | - An information page on [DeFi.vn](https://defi.vn) 44 | 45 | #### Rules 46 | - Open source 47 | - Bounty submission should be of good quality (well tested for core functionalities) 48 | 49 | --- 50 | 51 | ### Contribute a Telegram Bot to perform some actions on Klaytn 52 | 53 | Contribute a telegram bot 54 | 55 | #### Rewards 56 | - 500 KLAY per `merged` PR/submission 57 | 58 | #### Details 59 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 60 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 61 | - Can be forks 62 | 63 | #### Ideas 64 | - Telegram bot to check wallet balance 65 | - Telegram bot to manage and distribute NFTs 66 | - Telegram bot to trade on klaytn DEXes 67 | - Telegram bot to launch mint.club coins 68 | 69 | #### Rules 70 | - Open source 71 | - Bounty submission should be of good quality (well tested for core functionalities) 72 | 73 | --- 74 | 75 | ### Contribute a cool NFT implementation/forks on Klaytn 76 | 77 | #### Rewards 78 | - 100 - 800 KLAY per `merged` PR/submission 79 | 80 | #### Details 81 | - Propose an idea beforehand as an `issue` in the [Issue tab](https://github.com/klaytn/) 82 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 83 | - Can be forks 84 | 85 | #### Ideas 86 | - Nouns fork 87 | - DN404 tokens (hybrid NFT) 88 | - ERC6551 89 | 90 | #### Rules 91 | - Open source 92 | - Bounty submission should be of good quality (well tested for core functionalities) 93 | 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 2 | 3 | # NO LONGER MAINTAINED 4 | 5 | > [!IMPORTANT] 6 | > Since the launch of Kaia Blockchain, this repository has been parked in favour of the new open-source projects in [Kaia's Github](https://github.com/kaiachain). Contributors have now moved there continuing with massive open-source contributions to our blockchain ecosystem. A big thank you to everyone who has contributed to this repository. 7 | > 8 | > For future development and contributions, please refer to the new [kaia-dapp-mono repository](https://github.com/kaiachain/kaia-dapp-mono) 9 | > 10 | > More information about Klaytn's chain merge with Finschia blockchain, please refer to the launching of Kaia blockchain [kaia.io](https://kaia.io). 11 | 12 | --- 13 | 14 | ![Lone explorer in the dark forest](home-banner.png) 15 | # Klaytn DApp Toolkit 🧰 16 | 17 | > Start your web3 journey on Klaytn with a complete DApp toolkit 18 | 19 | **Klaytn DApp Toolkit** takes an unopinionated approach to DApp development. Instead of forcing you to adopt our tech stack of choice, we provide you with code snippets that you can use to copy and paste into whichever framework/technical stack that you are using. You can always refer to the original framework documentation for troubleshooting as well as our Troubleshooting section for each component. 20 | 21 | The included smart contract templates and front-end sample codes aim to provide you with everything you need to run a web product, along with additional tools, documentation, and tricks for building onchain. 22 | 23 | Whether you're a hackathon participant or an ambitious entrepreneur looking to establish the next successful project, this toolkit is designed with you in mind. 24 | 25 | ## Getting started 26 | ### Docs 27 | Read the [docs](/docs/README.md) in the repository for complete 28 | 29 | ### Contracts 30 | Contains many complete smart contract implementations of various DApps 31 | 32 | ### Frontend 33 | Contains implementation details of various frontend frameworks for EVM and guide to implement Klaytn specific features with copy/paste code samples 34 | 35 | ### Docker 36 | placeholder 37 | 38 | ### klaytn-hacker-house 39 | Contains details of bounty program on Klaytn Ecosystem 40 | 41 | ### Learn 42 | Includes various information pieces for the reference 43 | 44 | ### Workshops 45 | Contains workshop exercises 46 | 47 | ## FAQ 48 | ### Why copy/paste and not packaged as a container app? 49 | The idea behind this is to give you ownership and control over the code, allowing you to decide how the components of your DApp are built. 50 | 51 | Start with some sensible defaults, then customize all the codes to your needs. 52 | 53 | One of the drawback of other opinionated tools is that they often stick to one technical stack which might not fit for everyone. 54 | 55 | ### Do you plan to publish it as a container app? 56 | Not at the moment. 57 | 58 | ### Which frameworks are supported? 59 | You can use any development framework that supports EVM. For example, [Hardhat](https://hardhat.org), [Foundry](https://getfoundry.sh/), [Wagmi](https://wagmi.sh/), [Thirdweb](https://thirdweb.com/). You can also use dedicated toolings released by the Klaytn Foundation [here](https://github.com/klaytn) -------------------------------------------------------------------------------- /contracts/erc3156/test/01_FlashMinter.test.js: -------------------------------------------------------------------------------- 1 | const FlashMinter = artifacts.require('FlashMinterMock') 2 | const FlashBorrower = artifacts.require('FlashBorrower') 3 | 4 | const { BN, expectRevert } = require('@openzeppelin/test-helpers') 5 | require('chai').use(require('chai-as-promised')).should() 6 | 7 | const MAX = '115792089237316195423570985008687907853269984665640564039457584007913129639935' 8 | 9 | contract('FlashMinter', (accounts) => { 10 | const [deployer, user1] = accounts 11 | let lender 12 | let borrower 13 | let weth 14 | 15 | beforeEach(async () => { 16 | weth = await FlashMinter.new("Test", "TST", 10) 17 | lender = weth 18 | borrower = await FlashBorrower.new(lender.address) 19 | }) 20 | 21 | it('should do a simple flash loan', async () => { 22 | await borrower.flashBorrow(weth.address, 1, { from: user1 }) 23 | 24 | const balanceAfter = await lender.balanceOf(user1) 25 | balanceAfter.toString().should.equal(new BN('0').toString()) 26 | const flashBalance = await borrower.flashBalance() 27 | flashBalance.toString().should.equal(new BN('1').toString()) 28 | const flashToken = await borrower.flashToken() 29 | flashToken.toString().should.equal(weth.address) 30 | const flashAmount = await borrower.flashAmount() 31 | flashAmount.toString().should.equal(new BN('1').toString()) 32 | const flashInitiator = await borrower.flashInitiator() 33 | flashInitiator.toString().should.equal(borrower.address) 34 | }) 35 | 36 | it('should do a loan that pays fees', async () => { 37 | const loan = new BN('1000') 38 | const fee = await lender.flashFee(weth.address, loan) 39 | 40 | await weth.mint(borrower.address, 1, { from: user1 }) 41 | await borrower.flashBorrow(weth.address, loan, { from: user1 }) 42 | 43 | const balanceAfter = await lender.balanceOf(user1) 44 | balanceAfter.toString().should.equal('0') 45 | const flashBalance = await borrower.flashBalance() 46 | flashBalance.toString().should.equal(loan.add(fee).toString()) 47 | const flashToken = await borrower.flashToken() 48 | flashToken.toString().should.equal(weth.address) 49 | const flashAmount = await borrower.flashAmount() 50 | flashAmount.toString().should.equal(loan.toString()) 51 | const flashFee = await borrower.flashFee() 52 | flashFee.toString().should.equal(fee.toString()) 53 | const flashInitiator = await borrower.flashInitiator() 54 | flashInitiator.toString().should.equal(borrower.address) 55 | }) 56 | 57 | it('can not flash loan from an EOA', async () => { 58 | await expectRevert( 59 | lender.flashLoan(borrower.address, weth.address, 1, '0x0000000000000000000000000000000000000000000000000000000000000000', { from: user1 }), 60 | 'FlashBorrower: External loan initiator' 61 | ) 62 | }) 63 | 64 | it('needs to return funds after a flash loan', async () => { 65 | await expectRevert( 66 | borrower.flashBorrowAndSteal(weth.address, 1), 67 | 'FlashMinter: Repay not approved' 68 | ) 69 | }) 70 | 71 | it('should do two nested flash loans', async () => { 72 | await borrower.flashBorrowAndReenter(weth.address, 1) 73 | 74 | const flashBalance = await borrower.flashBalance() 75 | flashBalance.toString().should.equal('3') 76 | }) 77 | }) 78 | -------------------------------------------------------------------------------- /frontend/network/add-network-button.tsx: -------------------------------------------------------------------------------- 1 | interface Error { 2 | code: number 3 | message: string 4 | stack: string 5 | } 6 | 7 | export default function AddNetworkButton() { 8 | 9 | async function addKlaytnBaobabNetwork() { 10 | try { 11 | await window.ethereum.request({ 12 | "method": "wallet_addEthereumChain", 13 | "params": [ 14 | { 15 | "blockExplorerUrls": [ 16 | "https://baobab.klaytnfinder.io/" 17 | ], 18 | "iconUrls": [ 19 | "https://klaytn.foundation/wp-content/themes/klaytn/download/klaytn-symbol.png" 20 | ], 21 | "nativeCurrency": { 22 | "name": "KLAY", 23 | "symbol": "KLAY", 24 | "decimals": 18 25 | }, 26 | "rpcUrls": [ 27 | "https://rpc.ankr.com/klaytn_testnet" 28 | ], 29 | "chainId": "0x3e9", 30 | "chainName": "Klaytn Testnet Baobab" 31 | } 32 | ] 33 | }); 34 | await window.ethereum.request({ 35 | "method": "wallet_switchEthereumChain", 36 | "params": [ 37 | { 38 | "chainId": "0x3e9" 39 | } 40 | ] 41 | }); 42 | } catch (error) { 43 | // This error code indicates that the chain has not been added to MetaMask. 44 | if ((error as Error).code === 4001) { 45 | alert({ 46 | message: "User rejected to add network to Metamask", 47 | duration: 3000, 48 | }) 49 | } 50 | // handle other "switch" errors 51 | } 52 | } 53 | 54 | async function addKlaytnNetwork() { 55 | try { 56 | await window.ethereum.request({ 57 | "method": "wallet_addEthereumChain", 58 | "params": [ 59 | { 60 | "blockExplorerUrls": [ 61 | "https://klaytnfinder.io/" 62 | ], 63 | "iconUrls": [ 64 | "https://klaytn.foundation/wp-content/themes/klaytn/download/klaytn-symbol.png" 65 | ], 66 | "nativeCurrency": { 67 | "name": "KLAY", 68 | "symbol": "KLAY", 69 | "decimals": 18 70 | }, 71 | "rpcUrls": [ 72 | "https://rpc.ankr.com/klaytn" 73 | ], 74 | "chainId": "0x2019", 75 | "chainName": "Klaytn Mainnet Cypress" 76 | } 77 | ] 78 | }); 79 | await window.ethereum.request({ 80 | "method": "wallet_switchEthereumChain", 81 | "params": [ 82 | { 83 | "chainId": "0x2019" 84 | } 85 | ] 86 | }); 87 | } catch (error) { 88 | // This error code indicates that the chain has not been added to MetaMask. 89 | if ((error as Error).code === 4001) { 90 | alert({ 91 | message: "User rejected to add network to Metamask", 92 | duration: 3000, 93 | }) 94 | } 95 | // handle other "switch" errors 96 | } 97 | } 98 | 99 | return ( 100 | 103 | 106 | ) 107 | } 108 | -------------------------------------------------------------------------------- /contracts/CoinFlip/contract/CoinFlip.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.19; 3 | 4 | // Uncomment this line to use console.log 5 | // import "hardhat/console.sol"; 6 | import { VRFConsumerBase } from "@bisonai/orakl-contracts/src/v0.1/VRFConsumerBase.sol"; 7 | import { IVRFCoordinator } from "@bisonai/orakl-contracts/src/v0.1/interfaces/IVRFCoordinator.sol"; 8 | 9 | contract CoinFlip is VRFConsumerBase { 10 | 11 | enum CoinFlipChoice { 12 | HEADS, 13 | TAILS 14 | } 15 | 16 | struct CoinFlipStatus { 17 | uint256 fees; 18 | uint256 randomWord; 19 | address player; 20 | bool didWin; 21 | bool fulfilled; 22 | CoinFlipChoice choice; 23 | } 24 | 25 | error CoinFlip__EntryFeesNotEnough(); 26 | error CoinFlip__RequestNotFound(); 27 | 28 | mapping (uint256 => CoinFlipStatus) public s_status; 29 | 30 | uint256 public s_entryFees = 1 ether; 31 | 32 | uint256 private sRandomWord; 33 | IVRFCoordinator immutable i_vrfCoordinator; 34 | 35 | address private constant vrfAddress = 0xDA8c0A00A372503aa6EC80f9b29Cc97C454bE499; 36 | address private constant s_refundRecipient = 0x5664eeeE3C63431eF1981f2bDBaB2690ee33f1e8; 37 | uint32 private constant s_gasLane = 500000; 38 | uint32 private constant s_numWords = 1; 39 | bytes32 private constant s_keyHash = 40 | 0xd9af33106d664a53cb9946df5cd81a30695f5b72224ee64e798b278af812779c; 41 | 42 | constructor() VRFConsumerBase(vrfAddress) { 43 | i_vrfCoordinator = IVRFCoordinator(vrfAddress); 44 | } 45 | 46 | function flip(CoinFlipChoice choice) external payable returns(uint256 requestId){ 47 | if(msg.value < s_entryFees) { 48 | revert CoinFlip__EntryFeesNotEnough(); 49 | } 50 | 51 | requestId = i_vrfCoordinator.requestRandomWords( 52 | s_keyHash, 53 | s_gasLane, 54 | s_numWords, 55 | s_refundRecipient 56 | ); 57 | 58 | s_status[requestId] = CoinFlipStatus( 59 | { 60 | fees: s_gasLane, 61 | randomWord: 0, 62 | player: msg.sender, 63 | didWin: false, 64 | fulfilled: false, 65 | choice: choice 66 | } 67 | ); 68 | 69 | return requestId; 70 | } 71 | 72 | function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { 73 | if(s_status[requestId].fees < 0) { 74 | revert CoinFlip__RequestNotFound(); 75 | } 76 | 77 | s_status[requestId].fulfilled = true; 78 | s_status[requestId].randomWord = randomWords[0]; 79 | 80 | CoinFlipChoice result = CoinFlipChoice.HEADS; 81 | 82 | if(randomWords[0] % 2 == 0) { 83 | result = CoinFlipChoice.TAILS; // If the random Word is even, it is tails 84 | } 85 | 86 | if(s_status[requestId].choice == result) { 87 | s_status[requestId].didWin = true; 88 | (bool success, ) = payable(s_status[requestId].player).call{value: s_entryFees * 2}(""); 89 | require(success, "Transation failed"); 90 | } 91 | } 92 | 93 | function getStatus(uint256 requestId) public view returns(CoinFlipStatus memory) { 94 | return s_status[requestId]; 95 | } 96 | 97 | function getBalance() public view returns(uint256) { 98 | return address(this).balance; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /contracts/Minimal Proxy/minimalProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | contract MinimalProxyFactory { 6 | address[] public proxies; 7 | 8 | event Response(bool success, bytes data); 9 | 10 | function deployClone( 11 | address _implementationContract 12 | ) external returns (address) { 13 | // convert the address to 20 bytes 14 | bytes20 implementationContractInBytes = bytes20( 15 | _implementationContract 16 | ); 17 | //address to assign a cloned proxy 18 | address proxy; 19 | 20 | // as stated earlier, the minimal proxy has this bytecode 21 | // <3d602d80600a3d3981f3363d3d373d3d3d363d73>
<5af43d82803e903d91602b57fd5bf3> 22 | 23 | // <3d602d80600a3d3981f3> == creation code which copies runtime code into memory and deploys it 24 | 25 | // <363d3d373d3d3d363d73>
<5af43d82803e903d91602b57fd5bf3> == runtime code that makes a delegatecall to the implentation contract 26 | 27 | assembly { 28 | /* 29 | reads the 32 bytes of memory starting at the pointer stored in 0x40 30 | In solidity, the 0x40 slot in memory is special: it contains the "free memory pointer" 31 | which points to the end of the currently allocated memory. 32 | */ 33 | let clone := mload(0x40) 34 | // store 32 bytes to memory starting at "clone" 35 | mstore( 36 | clone, 37 | 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 38 | ) 39 | 40 | /* 41 | | 20 bytes | 42 | 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 43 | ^ 44 | pointer 45 | */ 46 | // store 32 bytes to memory starting at "clone" + 20 bytes 47 | // 0x14 = 20 48 | mstore(add(clone, 0x14), implementationContractInBytes) 49 | 50 | /* 51 | | 20 bytes | 20 bytes | 52 | 0x3d602d80600a3d3981f3363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe 53 | ^ 54 | pointer 55 | */ 56 | // store 32 bytes to memory starting at "clone" + 40 bytes 57 | // 0x28 = 40 58 | mstore( 59 | add(clone, 0x28), 60 | 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 61 | ) 62 | 63 | /* 64 | | 20 bytes | 20 bytes | 15 bytes | 65 | 0x3d602d80600a3d3981f3363d3d373d3d3d363d73b5af43d82803e903d91602b57fd5bf3 == 45 bytes in total 66 | */ 67 | 68 | // create a new contract 69 | // send 0 Ether 70 | // code starts at the pointer stored in "clone" 71 | // code size == 0x37 (55 bytes) 72 | proxy := create(0, clone, 0x37) 73 | } 74 | 75 | // Call initialization 76 | (bool success, bytes memory data) = proxy.call( 77 | abi.encodeWithSignature("setValue(uint256)", 123) 78 | ); 79 | 80 | emit Response(success, data); 81 | proxies.push(proxy); 82 | return proxy; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /contracts/erc3156/test/02_FlashLender.test.js: -------------------------------------------------------------------------------- 1 | const FlashLender = artifacts.require('FlashLender') 2 | const ERC20Mock = artifacts.require('ERC20Mock') 3 | const FlashBorrower = artifacts.require('FlashBorrower') 4 | 5 | const { BN, expectRevert } = require('@openzeppelin/test-helpers') 6 | require('chai').use(require('chai-as-promised')).should() 7 | 8 | const MAX = '115792089237316195423570985008687907853269984665640564039457584007913129639935' 9 | 10 | contract('FlashLender', (accounts) => { 11 | const [deployer, user1] = accounts 12 | let weth, dai 13 | let lender 14 | let borrower 15 | 16 | beforeEach(async () => { 17 | weth = await ERC20Mock.new("WETH", "WETH") 18 | dai = await ERC20Mock.new("DAI", "DAI") 19 | lender = await FlashLender.new([weth.address, dai.address], 10) 20 | borrower = await FlashBorrower.new(lender.address) 21 | 22 | await weth.mint(lender.address, 1000) 23 | await dai.mint(lender.address, 999) 24 | }) 25 | 26 | it('should do a simple flash loan', async () => { 27 | await borrower.flashBorrow(weth.address, 1, { from: user1 }) 28 | 29 | let balanceAfter = await weth.balanceOf(user1) 30 | balanceAfter.toString().should.equal(new BN('0').toString()) 31 | let flashBalance = await borrower.flashBalance() 32 | flashBalance.toString().should.equal(new BN('1').toString()) 33 | let flashToken = await borrower.flashToken() 34 | flashToken.toString().should.equal(weth.address) 35 | let flashAmount = await borrower.flashAmount() 36 | flashAmount.toString().should.equal(new BN('1').toString()) 37 | let flashInitiator = await borrower.flashInitiator() 38 | flashInitiator.toString().should.equal(borrower.address) 39 | 40 | await borrower.flashBorrow(dai.address, 3, { from: user1 }) 41 | 42 | balanceAfter = await dai.balanceOf(user1) 43 | balanceAfter.toString().should.equal(new BN('0').toString()) 44 | flashBalance = await borrower.flashBalance() 45 | flashBalance.toString().should.equal(new BN('3').toString()) 46 | flashToken = await borrower.flashToken() 47 | flashToken.toString().should.equal(dai.address) 48 | flashAmount = await borrower.flashAmount() 49 | flashAmount.toString().should.equal(new BN('3').toString()) 50 | flashInitiator = await borrower.flashInitiator() 51 | flashInitiator.toString().should.equal(borrower.address) 52 | }) 53 | 54 | it('should do a loan that pays fees', async () => { 55 | const loan = new BN('1000') 56 | const fee = await lender.flashFee(weth.address, loan) 57 | 58 | await weth.mint(borrower.address, 1, { from: user1 }) 59 | await borrower.flashBorrow(weth.address, loan, { from: user1 }) 60 | 61 | const balanceAfter = await weth.balanceOf(user1) 62 | balanceAfter.toString().should.equal(new BN('0').toString()) 63 | const flashBalance = await borrower.flashBalance() 64 | flashBalance.toString().should.equal(loan.add(fee).toString()) 65 | const flashToken = await borrower.flashToken() 66 | flashToken.toString().should.equal(weth.address) 67 | const flashAmount = await borrower.flashAmount() 68 | flashAmount.toString().should.equal(loan.toString()) 69 | const flashFee = await borrower.flashFee() 70 | flashFee.toString().should.equal(fee.toString()) 71 | const flashInitiator = await borrower.flashInitiator() 72 | flashInitiator.toString().should.equal(borrower.address) 73 | }) 74 | 75 | it('needs to return funds after a flash loan', async () => { 76 | await expectRevert( 77 | borrower.flashBorrowAndSteal(weth.address, 1), 78 | 'ERC20: insufficient-approval' 79 | ) 80 | }) 81 | 82 | it('should do two nested flash loans', async () => { 83 | await borrower.flashBorrowAndReenter(weth.address, 1) 84 | 85 | const flashBalance = await borrower.flashBalance() 86 | flashBalance.toString().should.equal('3') 87 | }) 88 | }) 89 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/reference/FlashMinter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../ERC20.sol"; 5 | import "../interfaces/IERC20.sol"; 6 | import "../interfaces/IERC3156FlashBorrower.sol"; 7 | import "../interfaces/IERC3156FlashLender.sol"; 8 | 9 | 10 | /** 11 | * @author Alberto Cuesta Cañada 12 | * @dev Extension of {ERC20} that allows flash minting. 13 | */ 14 | contract FlashMinter is ERC20, IERC3156FlashLender { 15 | 16 | bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); 17 | uint256 public fee; // 1 == 0.01 %. 18 | 19 | /** 20 | * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`. 21 | */ 22 | constructor ( 23 | string memory name, 24 | string memory symbol, 25 | uint256 fee_ 26 | ) ERC20(name, symbol) { 27 | fee = fee_; 28 | } 29 | 30 | /** 31 | * @dev The amount of currency available to be lended. 32 | * @param token The loan currency. 33 | * @return The amount of `token` that can be borrowed. 34 | */ 35 | function maxFlashLoan( 36 | address token 37 | ) external view override returns (uint256) { 38 | return type(uint256).max - totalSupply(); 39 | } 40 | 41 | /** 42 | * @dev The fee to be charged for a given loan. 43 | * @param token The loan currency. Must match the address of this contract. 44 | * @param amount The amount of tokens lent. 45 | * @return The amount of `token` to be charged for the loan, on top of the returned principal. 46 | */ 47 | function flashFee( 48 | address token, 49 | uint256 amount 50 | ) external view override returns (uint256) { 51 | require( 52 | token == address(this), 53 | "FlashMinter: Unsupported currency" 54 | ); 55 | return _flashFee(token, amount); 56 | } 57 | 58 | /** 59 | * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the ERC3156 callback. 60 | * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface. 61 | * @param token The loan currency. Must match the address of this contract. 62 | * @param amount The amount of tokens lent. 63 | * @param data A data parameter to be passed on to the `receiver` for any custom use. 64 | */ 65 | function flashLoan( 66 | IERC3156FlashBorrower receiver, 67 | address token, 68 | uint256 amount, 69 | bytes calldata data 70 | ) external override returns (bool){ 71 | require( 72 | token == address(this), 73 | "FlashMinter: Unsupported currency" 74 | ); 75 | uint256 _fee = _flashFee(token, amount); 76 | _mint(address(receiver), amount); 77 | require( 78 | receiver.onFlashLoan(msg.sender, token, amount, _fee, data) == CALLBACK_SUCCESS, 79 | "FlashMinter: Callback failed" 80 | ); 81 | uint256 _allowance = allowance(address(receiver), address(this)); 82 | require( 83 | _allowance >= (amount + _fee), 84 | "FlashMinter: Repay not approved" 85 | ); 86 | _approve(address(receiver), address(this), _allowance - (amount + _fee)); 87 | _burn(address(receiver), amount + _fee); 88 | return true; 89 | } 90 | 91 | /** 92 | * @dev The fee to be charged for a given loan. Internal function with no checks. 93 | * @param token The loan currency. 94 | * @param amount The amount of tokens lent. 95 | * @return The amount of `token` to be charged for the loan, on top of the returned principal. 96 | */ 97 | function _flashFee( 98 | address token, 99 | uint256 amount 100 | ) internal view returns (uint256) { 101 | return amount * fee / 10000; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/reference/FlashLender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../interfaces/IERC20.sol"; 5 | import "../interfaces/IERC3156FlashBorrower.sol"; 6 | import "../interfaces/IERC3156FlashLender.sol"; 7 | 8 | 9 | /** 10 | * @author Alberto Cuesta Cañada 11 | * @dev Extension of {ERC20} that allows flash lending. 12 | */ 13 | contract FlashLender is IERC3156FlashLender { 14 | 15 | bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); 16 | mapping(address => bool) public supportedTokens; 17 | uint256 public fee; // 1 == 0.01 %. 18 | 19 | 20 | /** 21 | * @param supportedTokens_ Token contracts supported for flash lending. 22 | * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`. 23 | */ 24 | constructor( 25 | address[] memory supportedTokens_, 26 | uint256 fee_ 27 | ) { 28 | for (uint256 i = 0; i < supportedTokens_.length; i++) { 29 | supportedTokens[supportedTokens_[i]] = true; 30 | } 31 | fee = fee_; 32 | } 33 | 34 | /** 35 | * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the callback. 36 | * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface. 37 | * @param token The loan currency. 38 | * @param amount The amount of tokens lent. 39 | * @param data A data parameter to be passed on to the `receiver` for any custom use. 40 | */ 41 | function flashLoan( 42 | IERC3156FlashBorrower receiver, 43 | address token, 44 | uint256 amount, 45 | bytes calldata data 46 | ) external override returns(bool) { 47 | require( 48 | supportedTokens[token], 49 | "FlashLender: Unsupported currency" 50 | ); 51 | uint256 _fee = _flashFee(token, amount); 52 | require( 53 | IERC20(token).transfer(address(receiver), amount), 54 | "FlashLender: Transfer failed" 55 | ); 56 | require( 57 | receiver.onFlashLoan(msg.sender, token, amount, _fee, data) == CALLBACK_SUCCESS, 58 | "FlashLender: Callback failed" 59 | ); 60 | require( 61 | IERC20(token).transferFrom(address(receiver), address(this), amount + _fee), 62 | "FlashLender: Repay failed" 63 | ); 64 | return true; 65 | } 66 | 67 | /** 68 | * @dev The fee to be charged for a given loan. 69 | * @param token The loan currency. 70 | * @param amount The amount of tokens lent. 71 | * @return The amount of `token` to be charged for the loan, on top of the returned principal. 72 | */ 73 | function flashFee( 74 | address token, 75 | uint256 amount 76 | ) external view override returns (uint256) { 77 | require( 78 | supportedTokens[token], 79 | "FlashLender: Unsupported currency" 80 | ); 81 | return _flashFee(token, amount); 82 | } 83 | 84 | /** 85 | * @dev The fee to be charged for a given loan. Internal function with no checks. 86 | * @param token The loan currency. 87 | * @param amount The amount of tokens lent. 88 | * @return The amount of `token` to be charged for the loan, on top of the returned principal. 89 | */ 90 | function _flashFee( 91 | address token, 92 | uint256 amount 93 | ) internal view returns (uint256) { 94 | return amount * fee / 10000; 95 | } 96 | 97 | /** 98 | * @dev The amount of currency available to be lended. 99 | * @param token The loan currency. 100 | * @return The amount of `token` that can be borrowed. 101 | */ 102 | function maxFlashLoan( 103 | address token 104 | ) external view override returns (uint256) { 105 | return supportedTokens[token] ? IERC20(token).balanceOf(address(this)) : 0; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /contracts/erc5115/src/abstracts/RewardManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "../interfaces/IStandardizedYield.sol"; 5 | import "../interfaces/IRewardManager.sol"; 6 | import "../libraries/SYMath.sol"; 7 | import "../libraries/TokenHelper.sol"; 8 | 9 | abstract contract RewardManager is IRewardManager, TokenHelper { 10 | using SYMath for uint256; 11 | 12 | uint256 public lastRewardBlock; 13 | 14 | struct RewardState { 15 | uint256 index; 16 | uint256 lastBalance; 17 | } 18 | 19 | uint256 internal constant INITIAL_REWARD_INDEX = 1; 20 | 21 | mapping(address => RewardState) public rewardState; 22 | mapping(address => mapping(address => uint256)) public userRewardAccrued; 23 | mapping(address => mapping(address => uint256)) public userRewardIndex; 24 | 25 | function _getRewardTokens() internal view virtual returns (address[] memory); 26 | 27 | function _updateAndDistributeReward(address user) internal virtual { 28 | _updateRewardIndex(); 29 | _distributeUserReward(user); 30 | } 31 | 32 | function _updateRewardIndex() internal virtual { 33 | if (lastRewardBlock == block.number) return; 34 | lastRewardBlock = block.number; 35 | 36 | _redeemExternalReward(); 37 | 38 | uint256 totalShares = _rewardSharesTotal(); 39 | 40 | address[] memory rewardTokens = _getRewardTokens(); 41 | 42 | for (uint256 i = 0; i < rewardTokens.length; ++i) { 43 | address token = rewardTokens[i]; 44 | 45 | uint256 rewardIndex = rewardState[token].index; 46 | 47 | uint256 currentBalance = _selfBalance(token); 48 | uint256 rewardAccrued = currentBalance - rewardState[token].lastBalance; 49 | 50 | if (rewardIndex == 0) rewardIndex = INITIAL_REWARD_INDEX; 51 | if (totalShares != 0) rewardIndex += rewardAccrued.divDown(totalShares); 52 | 53 | rewardState[token] = RewardState({index: rewardIndex, lastBalance: currentBalance}); 54 | } 55 | } 56 | 57 | function _distributeUserReward(address user) internal virtual { 58 | address[] memory rewardTokens = _getRewardTokens(); 59 | 60 | uint256 userShares = _rewardSharesUser(user); 61 | 62 | for (uint256 i = 0; i < rewardTokens.length; ++i) { 63 | address token = rewardTokens[i]; 64 | 65 | uint256 rewardIndex = rewardState[token].index; 66 | uint256 userIndex = userRewardIndex[user][token]; 67 | 68 | if (userIndex == 0 && rewardIndex > 0) { 69 | userIndex = INITIAL_REWARD_INDEX; 70 | } 71 | 72 | uint256 deltaIndex = rewardIndex - userIndex; 73 | uint256 rewardDelta = userShares.mulDown(deltaIndex); 74 | uint256 rewardAccrued = userRewardAccrued[user][token] + rewardDelta; 75 | 76 | userRewardAccrued[user][token] = rewardAccrued; 77 | userRewardIndex[user][token] = rewardIndex; 78 | } 79 | } 80 | 81 | function _doTransferOutRewards(address user, address receiver) 82 | internal 83 | virtual 84 | returns (uint256[] memory rewardAmounts) 85 | { 86 | address[] memory rewardTokens = _getRewardTokens(); 87 | 88 | rewardAmounts = new uint256[](rewardTokens.length); 89 | for (uint256 i = 0; i < rewardTokens.length; ++i) { 90 | address token = rewardTokens[i]; 91 | 92 | rewardAmounts[i] = userRewardAccrued[user][token]; 93 | userRewardAccrued[user][token] = 0; 94 | 95 | rewardState[token].lastBalance -= rewardAmounts[i]; 96 | 97 | if (rewardAmounts[i] != 0) { 98 | _transferOut(token, receiver, rewardAmounts[i]); 99 | } 100 | } 101 | } 102 | 103 | /// @dev to be overriden if there is rewards 104 | function _redeemExternalReward() internal virtual; 105 | 106 | /// @dev to be overriden if there is rewards 107 | function _rewardSharesTotal() internal virtual returns (uint256); 108 | 109 | /// @dev to be overriden if there is rewards 110 | function _rewardSharesUser(address /*user*/ ) internal virtual returns (uint256); 111 | } 112 | -------------------------------------------------------------------------------- /contracts/erc3156/contracts/ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | /// ERC20.sol -- ERC20 implementation with minting and burning 3 | // Inspired on token.sol from DappHub 4 | 5 | // Copyright (C) 2015, 2016, 2017 DappHub, LLC 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | pragma solidity ^0.8.0; 21 | 22 | 23 | contract ERC20 { 24 | uint256 internal _totalSupply; 25 | mapping (address => uint256) internal _balanceOf; 26 | mapping (address => mapping (address => uint256)) internal _allowance; 27 | string public symbol; 28 | uint256 public decimals = 18; // standard token precision. override to customize 29 | string public name = ""; // Optional token name 30 | 31 | constructor(string memory name_, string memory symbol_) { 32 | name = name_; 33 | symbol = symbol_; 34 | } 35 | 36 | event Approval(address indexed owner, address indexed spender, uint wad); 37 | event Transfer(address indexed src, address indexed dst, uint wad); 38 | event Mint(address indexed dst, uint wad); 39 | event Burn(address indexed src, uint wad); 40 | 41 | function totalSupply() public view returns (uint256) { 42 | return _totalSupply; 43 | } 44 | 45 | function balanceOf(address guy) public view returns (uint256) { 46 | return _balanceOf[guy]; 47 | } 48 | 49 | function allowance(address owner, address spender) public view returns (uint256) { 50 | return _allowance[owner][spender]; 51 | } 52 | 53 | function approve(address spender, uint wad) public returns (bool) { 54 | return _approve(msg.sender, spender, wad); 55 | } 56 | 57 | function transfer(address dst, uint wad) external returns (bool) { 58 | return transferFrom(msg.sender, dst, wad); 59 | } 60 | 61 | function transferFrom(address src, address dst, uint wad) public returns (bool) { 62 | uint256 allowed = _allowance[src][msg.sender]; 63 | if (src != msg.sender && allowed != type(uint).max) { 64 | require(allowed >= wad, "ERC20: insufficient-approval"); 65 | _approve(src, msg.sender, allowed - wad); 66 | } 67 | 68 | require(_balanceOf[src] >= wad, "ERC20: insufficient-balance"); 69 | _balanceOf[src] = _balanceOf[src] - wad; 70 | _balanceOf[dst] = _balanceOf[dst] + wad; 71 | 72 | emit Transfer(src, dst, wad); 73 | 74 | return true; 75 | } 76 | 77 | function _approve(address owner, address spender, uint wad) internal returns (bool) { 78 | _allowance[owner][spender] = wad; 79 | emit Approval(owner, spender, wad); 80 | return true; 81 | } 82 | 83 | function _mint(address dst, uint wad) internal { 84 | _balanceOf[dst] = _balanceOf[dst] + wad; 85 | _totalSupply = _totalSupply + wad; 86 | emit Mint(dst, wad); 87 | } 88 | 89 | function _burn(address src, uint wad) internal { 90 | uint256 allowed = _allowance[src][msg.sender]; 91 | if (src != msg.sender && allowed != type(uint).max) { 92 | require(allowed >= wad, "ERC20: insufficient-approval"); 93 | _approve(src, msg.sender, allowed - wad); 94 | } 95 | 96 | require(_balanceOf[src] >= wad, "ERC20: insufficient-balance"); 97 | _balanceOf[src] = _balanceOf[src] - wad; 98 | _totalSupply = _totalSupply - wad; 99 | emit Burn(src, wad); 100 | } 101 | } -------------------------------------------------------------------------------- /contracts/ContriBoost/README.md: -------------------------------------------------------------------------------- 1 | # Contribution System Contract 2 | 3 | ## Deployed contract Addresses 4 | - [Smart Contract Address for Contribution System](https://baobab.klaytnscope.com/account/0x4a16834828a148371a5cbf41340b6bdbb313aa4d?tabId=contractCode): `0x4a16834828a148371a5cbf41340b6bdbb313aa4d` 5 | - [Factory Contract Address for Contribution System](https://baobab.klaytnscope.com/account/0x90a77a567c4ebc6c1fef3dcbdc61ff94f1a16ea2?tabId=contractCode): `0x90a77a567c4ebc6c1fef3dcbdc61ff94f1a16ea2` 6 | 7 | This Solidity contract is a contribution system that allows participants to join, deposit funds, and then distributes those funds randomly among the participants at the end of each segment. Let's break down the code: 8 | 9 | ## Contract Structure 10 | - The contract is named `ContributionSystem`. 11 | - It uses Solidity version `^0.8.19`. 12 | - The SPDX-License-Identifier is set to MIT, indicating the license under which the contract's code is available. 13 | 14 | ## State Variables 15 | - `host`: Stores the address of the contract deployer, who is also the host of the contribution system. 16 | - `dayRange`: Represents the duration of each segment in days. 17 | - `expectedNumber`: Specifies the expected number of participants. 18 | - `currentSegment`: Tracks the current segment. 19 | - `contributionAmount`: Indicates the expected amount each participant should contribute. 20 | - `tokenAddress`: Stores the address of the ERC20 token used for contributions. 21 | - `participants`: Maps participant addresses to their Participant struct. 22 | - `participantList`: Stores the addresses of all participants. 23 | - `totalAmount`: Total amount of tokens in the contract. 24 | 25 | ## Participant Struct 26 | Defines the `Participant` struct with fields for id, depositAmount, lastDepositTime, existence status, and whether they've received funds. 27 | 28 | ## Events 29 | - `Deposit`: Triggered when a participant makes a deposit. 30 | - `FundsTransferred`: Triggered when funds are transferred from the contract to a participant. 31 | - `SegmentEnd`: Triggered when a segment ends. 32 | - `RandomNumberGenerated`: Triggered when a random number is generated. 33 | 34 | ## VRF (Verifiable Random Function) 35 | - The contract inherits from `VRFConsumerBase` to implement the VRF feature. 36 | - `COORDINATOR`: A reference to the VRF Coordinator. 37 | - `keyHash`: A unique key hash for VRF request. 38 | - `fee`: The fee required to make a request. 39 | - `sRandomWord`: Holds the random number generated by the VRF. 40 | 41 | ## Constructor 42 | Initializes contract variables including `host`, `dayRange`, `expectedNumber`, `contributionAmount`, and `tokenAddress`. It also initializes VRF related variables. 43 | 44 | ## Modifiers 45 | - `onlyHost`: Restricts access to functions only to the contract host. 46 | - `canJoin`: Ensures that only non-participants can join. 47 | 48 | ## Functions 49 | - `join`: Allows participants to join the system by adding them to `participantList`. 50 | - `deposit`: Allows participants to deposit funds into the contract. 51 | - `distributeFunds`: Distributes funds to a random participant at the end of each segment, deducts 2% as the host share, and increments the segment count. 52 | - `getRandomParticipant`: Returns a random participant from the `participantList`. 53 | - `withdraw`: Allows the contract host to withdraw remaining funds. 54 | - `requestRandomWords`: Requests a random number from the VRF Coordinator. 55 | - `fulfillRandomWords`: Callback function that fulfills the random number request and transfers funds to the randomly chosen participant. 56 | 57 | ## ContributionSystemFactory Contract 58 | This contract allows deploying multiple instances of the `ContributionSystem` contract. 59 | 60 | ## Functions 61 | - `createContributionSystem`: Allows creating a new instance of the `ContributionSystem` contract. 62 | - `getDeployedSystems`: Returns the list of deployed systems. 63 | - `getSystemsByCreator`: Returns the list of systems deployed by a specific creator. 64 | 65 | ## Explanation of Changes 66 | - The `distributeFunds` function now checks if the expected number of participants has been met before distributing funds. 67 | - The `deposit` function allows participants to deposit funds incrementally over the day range. 68 | 69 | This contract aims to create a fair and transparent contribution system where funds are distributed randomly among participants at the end of each segment. 70 | -------------------------------------------------------------------------------- /contracts/erc5115/src/samples/YearnVaultSY.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "../abstracts/SYBase.sol"; 5 | import "../interfaces/IYearnVault.sol"; 6 | 7 | contract YearnVaultSY is SYBase { 8 | address public immutable underlying; 9 | address public immutable yvToken; 10 | 11 | uint256 public override exchangeRateStored; 12 | 13 | constructor(string memory _name, string memory _symbol, address _underlying, address _yvToken) 14 | SYBase(_name, _symbol, _yvToken) 15 | { 16 | require(_yvToken != address(0), "zero address"); 17 | yvToken = _yvToken; 18 | underlying = _underlying; 19 | _safeApprove(underlying, yvToken, type(uint256).max); 20 | } 21 | 22 | /*/////////////////////////////////////////////////////////////// 23 | DEPOSIT/REDEEM USING BASE TOKENS 24 | //////////////////////////////////////////////////////////////*/ 25 | 26 | /** 27 | * @dev See {SCYBase-_deposit} 28 | * 29 | * The underlying yield token is yvToken. If the base token deposited is underlying asset, the function 30 | * first mints yvToken using those deposited. Then the corresponding amount of shares is returned. 31 | * 32 | * The exchange rate of yvToken to shares is 1:1 33 | */ 34 | function _deposit(address tokenIn, uint256 amountDeposited) 35 | internal 36 | virtual 37 | override 38 | returns (uint256 amountSharesOut) 39 | { 40 | if (tokenIn == yvToken) { 41 | amountSharesOut = amountDeposited; 42 | } else { 43 | // tokenIn == underlying 44 | uint256 preBalance = _selfBalance(yvToken); 45 | IYearnVault(yvToken).deposit(amountDeposited); 46 | amountSharesOut = _selfBalance(yvToken) - preBalance; // 1 yvToken = 1 SCY 47 | } 48 | } 49 | 50 | /** 51 | * @dev See {SCYBase-_redeem} 52 | * 53 | * The shares are redeemed into the same amount of yvTokens. If `tokenOut` is the underlying asset, 54 | * the function also withdraws said asset for redemption, using the corresponding amount of yvToken. 55 | */ 56 | function _redeem(address tokenOut, uint256 amountSharesToRedeem) 57 | internal 58 | virtual 59 | override 60 | returns (uint256 amountTokenOut) 61 | { 62 | if (tokenOut == yvToken) { 63 | amountTokenOut = amountSharesToRedeem; 64 | } else { 65 | // tokenOut == underlying 66 | IYearnVault(yvToken).withdraw(amountSharesToRedeem); 67 | amountTokenOut = _selfBalance(underlying); 68 | } 69 | } 70 | 71 | /*/////////////////////////////////////////////////////////////// 72 | EXCHANGE-RATE 73 | //////////////////////////////////////////////////////////////*/ 74 | 75 | /** 76 | * @notice Calculates and updates the exchange rate of shares to underlying asset token 77 | * @dev It is the price per share of the yvToken 78 | */ 79 | function exchangeRateCurrent() public override returns (uint256 currentRate) { 80 | currentRate = IYearnVault(yvToken).pricePerShare(); 81 | 82 | emit ExchangeRateUpdated(exchangeRateStored, currentRate); 83 | 84 | exchangeRateStored = currentRate; 85 | } 86 | 87 | /*/////////////////////////////////////////////////////////////// 88 | MISC FUNCTIONS FOR METADATA 89 | //////////////////////////////////////////////////////////////*/ 90 | 91 | /** 92 | * @dev See {ISuperComposableYield-getBaseTokens} 93 | */ 94 | function getBaseTokens() public view virtual override returns (address[] memory res) { 95 | res = new address[](2); 96 | res[0] = underlying; 97 | res[1] = yvToken; 98 | } 99 | 100 | /** 101 | * @dev See {ISuperComposableYield-isValidBaseToken} 102 | */ 103 | function isValidBaseToken(address token) public view virtual override returns (bool) { 104 | return token == underlying || token == yvToken; 105 | } 106 | 107 | function assetInfo() external view returns (AssetType assetType, address assetAddress, uint8 assetDecimals) { 108 | return (AssetType.TOKEN, underlying, IERC20Metadata(underlying).decimals()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/contracts/MultiTierReferralSystem.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; 6 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; 7 | 8 | contract MultiTierReferralSystem is ReentrancyGuard, ERC721Enumerable { 9 | IERC20 private tokenUSDC; 10 | 11 | // Can set it according wishes up to 10 level 12 | uint256[] private shareValue = [ 13 | 10e6, // $10 14 | 10e6, // $10 15 | 10e6, // $10 16 | 10e6, // $10 17 | 10e6, // $10 18 | 10e6, // $10 19 | 10e6, // $10 20 | 10e6, // $10 21 | 10e6, // $10 22 | 10e6 // $10 23 | ]; 24 | uint256 public lastUplineTokenId; 25 | 26 | mapping(uint256 => uint256) public lineTier; 27 | mapping(uint256 => uint256) public receivedUSDC; 28 | 29 | event Registration(uint256 indexed newTokenId, uint256 indexed uplineTokenId, uint256 indexed timestamp); 30 | 31 | constructor(address _addressUSDC, address _defaultUplineAddress) ERC721("Multi-Tier Referral System", "MTRS") { 32 | tokenUSDC = IERC20(_addressUSDC); 33 | for (uint256 i = shareValue.length; i > 0; i--) { 34 | lineTier[i] = i - 1; 35 | _safeMint(_defaultUplineAddress, i); 36 | } 37 | lastUplineTokenId = shareValue.length; 38 | } 39 | 40 | function registration(uint256 _uplineTokenId, uint256 _newTokenId) external nonReentrant { 41 | uint256 lengthShareValue = shareValue.length; 42 | require(_newTokenId > lengthShareValue, "Set new tokenId"); 43 | require(_uplineTokenId == 0 || _requireOwned(_uplineTokenId) != address(0), "Upline tokenId not already minted"); 44 | address who = _msgSender(); 45 | 46 | uint256 uplineTokenId = _uplineTokenId > lengthShareValue ? _uplineTokenId : lastUplineTokenId; 47 | lineTier[_newTokenId] = uplineTokenId; 48 | 49 | uint256 profit; 50 | uint256 currentUplineTokenId = uplineTokenId; 51 | for (uint256 i = 0; i < lengthShareValue; i++) { 52 | profit = shareValue[i]; 53 | receivedUSDC[currentUplineTokenId] += profit; 54 | tokenUSDC.transferFrom(who, ownerOf(currentUplineTokenId), profit); 55 | currentUplineTokenId = lineTier[currentUplineTokenId]; 56 | } 57 | 58 | _safeMint(who, _newTokenId); 59 | emit Registration(_newTokenId, uplineTokenId, block.timestamp); 60 | } 61 | 62 | function rangeTokenIds(address _who, uint256 _startIndex, uint256 _stopIndex) public view returns (uint256[] memory) { 63 | uint256 lengthOwned = _stopIndex - _startIndex; 64 | uint256[] memory ownedTokenIds = new uint256[](lengthOwned); 65 | uint256 index = 0; 66 | for (uint i = _startIndex; i < (_stopIndex + 1); i++) { 67 | ownedTokenIds[index] = tokenOfOwnerByIndex(_who, i); 68 | index++; 69 | } 70 | return ownedTokenIds; 71 | } 72 | 73 | function rangeInfo(address _who, uint256 _startIndex, uint256 _stopIndex) external view returns (uint256[] memory, uint256[] memory) { 74 | uint256[] memory ownedTokenIds = rangeTokenIds(_who, _startIndex, _stopIndex); 75 | uint256[] memory profitUSDCByTokenId = new uint256[](ownedTokenIds.length); 76 | for (uint i = 0; i < ownedTokenIds.length; i++) { 77 | profitUSDCByTokenId[i] = receivedUSDC[ownedTokenIds[i]]; 78 | } 79 | return (ownedTokenIds, profitUSDCByTokenId); 80 | } 81 | 82 | function allTokenIds(address _who) public view returns (uint256[] memory) { 83 | uint256 lengthOwned = balanceOf(_who); 84 | uint256[] memory ownedTokenIds = new uint256[](lengthOwned); 85 | for (uint i = 0; i < lengthOwned; i++) { 86 | ownedTokenIds[i] = tokenOfOwnerByIndex(_who, i); 87 | } 88 | return ownedTokenIds; 89 | } 90 | 91 | function allInfo(address _who) external view returns (uint256[] memory, uint256[] memory) { 92 | uint256[] memory ownedTokenIds = allTokenIds(_who); 93 | uint256[] memory profitUSDCByTokenId = new uint256[](ownedTokenIds.length); 94 | for (uint i = 0; i < ownedTokenIds.length; i++) { 95 | profitUSDCByTokenId[i] = receivedUSDC[ownedTokenIds[i]]; 96 | } 97 | return (ownedTokenIds, profitUSDCByTokenId); 98 | } 99 | } -------------------------------------------------------------------------------- /contracts/erc3156/testlog.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Contract: FlashMinter 5 | ✔ should do a simple flash loan 6 | ✔ should do a loan that pays fees 7 | @openzeppelin/test-helpers WARN expectRevert: Assertions may yield false negatives! 8 | 9 | Revert reason checks are only known to work on Ganache >=2.2.0 and Hardhat, and the current node is HardhatNetwork/2.21.0/@nomicfoundation/edr/0.2.0-dev. 10 | 11 | If your node does support revert reasons, please let us know: https://github.com/OpenZeppelin/openzeppelin-test-helpers/issues/new 12 | ✔ can not flash loan from an EOA 13 | ✔ needs to return funds after a flash loan 14 | ✔ should do two nested flash loans 15 | 16 | Contract: FlashLender 17 | ✔ should do a simple flash loan 18 | ✔ should do a loan that pays fees 19 | ✔ needs to return funds after a flash loan 20 | ✔ should do two nested flash loans 21 | 22 | ·---------------------------------------------|----------------------------|-------------|-----------------------------· 23 | | Solc version: 0.8.0 · Optimizer enabled: false · Runs: 200 · Block limit: 30000000 gas │ 24 | ··············································|····························|·············|······························ 25 | | Methods │ 26 | ····················|·························|··············|·············|·············|···············|·············· 27 | | Contract · Method · Min · Max · Avg · # calls · eur (avg) │ 28 | ····················|·························|··············|·············|·············|···············|·············· 29 | | ERC20Mock · mint · 51505 · 68617 · 66716 · 9 · - │ 30 | ····················|·························|··············|·············|·············|···············|·············· 31 | | FlashBorrower · flashBorrow · 109344 · 185991 · 161025 · 5 · - │ 32 | ····················|·························|··············|·············|·············|···············|·············· 33 | | FlashBorrower · flashBorrowAndReenter · 194092 · 198089 · 196091 · 2 · - │ 34 | ····················|·························|··············|·············|·············|···············|·············· 35 | | FlashMinterMock · mint · - · - · 68672 · 1 · - │ 36 | ····················|·························|··············|·············|·············|···············|·············· 37 | | Deployments · · % of limit · │ 38 | ··············································|··············|·············|·············|···············|·············· 39 | | ERC20Mock · 921125 · 921149 · 921137 · 3.1 % · - │ 40 | ··············································|··············|·············|·············|···············|·············· 41 | | FlashBorrower · 1078594 · 1078606 · 1078605 · 3.6 % · - │ 42 | ··············································|··············|·············|·············|···············|·············· 43 | | FlashLender · 936681 · 936693 · 936690 · 3.1 % · - │ 44 | ··············································|··············|·············|·············|···············|·············· 45 | | FlashMinterMock · - · - · 1567090 · 5.2 % · - │ 46 | ·---------------------------------------------|--------------|-------------|-------------|---------------|-------------· 47 | 48 | 9 passing (698ms) 49 | 50 | -------------------------------------------------------------------------------- /contracts/crowd-fund/CrowdFund.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | interface IERC20 { 5 | function transfer(address, uint) external returns (bool); 6 | 7 | function transferFrom(address, address, uint) external returns (bool); 8 | } 9 | 10 | contract CrowdFund { 11 | event Launch( 12 | uint id, 13 | address indexed creator, 14 | uint goal, 15 | uint32 startAt, 16 | uint32 endAt 17 | ); 18 | event Cancel(uint id); 19 | event Pledge(uint indexed id, address indexed caller, uint amount); 20 | event Unpledge(uint indexed id, address indexed caller, uint amount); 21 | event Claim(uint id); 22 | event Refund(uint id, address indexed caller, uint amount); 23 | 24 | struct Campaign { 25 | // Creator of campaign 26 | address creator; 27 | // Amount of tokens to raise 28 | uint goal; 29 | // Total amount pledged 30 | uint pledged; 31 | // Timestamp of start of campaign 32 | uint32 startAt; 33 | // Timestamp of end of campaign 34 | uint32 endAt; 35 | // True if goal was reached and creator has claimed the tokens. 36 | bool claimed; 37 | } 38 | 39 | IERC20 public immutable token; 40 | // Total count of campaigns created. 41 | // It is also used to generate id for new campaigns. 42 | uint public count; 43 | // Mapping from id to Campaign 44 | mapping(uint => Campaign) public campaigns; 45 | // Mapping from campaign id => pledger => amount pledged 46 | mapping(uint => mapping(address => uint)) public pledgedAmount; 47 | 48 | constructor(address _token) { 49 | token = IERC20(_token); 50 | } 51 | 52 | function launch(uint _goal, uint32 _startAt, uint32 _endAt) external { 53 | require(_startAt >= block.timestamp, "start at < now"); 54 | require(_endAt >= _startAt, "end at < start at"); 55 | require(_endAt <= block.timestamp + 90 days, "end at > max duration"); 56 | 57 | count += 1; 58 | campaigns[count] = Campaign({ 59 | creator: msg.sender, 60 | goal: _goal, 61 | pledged: 0, 62 | startAt: _startAt, 63 | endAt: _endAt, 64 | claimed: false 65 | }); 66 | 67 | emit Launch(count, msg.sender, _goal, _startAt, _endAt); 68 | } 69 | 70 | function cancel(uint _id) external { 71 | Campaign memory campaign = campaigns[_id]; 72 | require(campaign.creator == msg.sender, "not creator"); 73 | require(block.timestamp < campaign.startAt, "started"); 74 | 75 | delete campaigns[_id]; 76 | emit Cancel(_id); 77 | } 78 | 79 | function pledge(uint _id, uint _amount) external { 80 | Campaign storage campaign = campaigns[_id]; 81 | require(block.timestamp >= campaign.startAt, "not started"); 82 | require(block.timestamp <= campaign.endAt, "ended"); 83 | 84 | campaign.pledged += _amount; 85 | pledgedAmount[_id][msg.sender] += _amount; 86 | token.transferFrom(msg.sender, address(this), _amount); 87 | 88 | emit Pledge(_id, msg.sender, _amount); 89 | } 90 | 91 | function unpledge(uint _id, uint _amount) external { 92 | Campaign storage campaign = campaigns[_id]; 93 | require(block.timestamp <= campaign.endAt, "ended"); 94 | 95 | campaign.pledged -= _amount; 96 | pledgedAmount[_id][msg.sender] -= _amount; 97 | token.transfer(msg.sender, _amount); 98 | 99 | emit Unpledge(_id, msg.sender, _amount); 100 | } 101 | 102 | function claim(uint _id) external { 103 | Campaign storage campaign = campaigns[_id]; 104 | require(campaign.creator == msg.sender, "not creator"); 105 | require(block.timestamp > campaign.endAt, "not ended"); 106 | require(campaign.pledged >= campaign.goal, "pledged < goal"); 107 | require(!campaign.claimed, "claimed"); 108 | 109 | campaign.claimed = true; 110 | token.transfer(campaign.creator, campaign.pledged); 111 | 112 | emit Claim(_id); 113 | } 114 | 115 | function refund(uint _id) external { 116 | Campaign memory campaign = campaigns[_id]; 117 | require(block.timestamp > campaign.endAt, "not ended"); 118 | require(campaign.pledged < campaign.goal, "pledged >= goal"); 119 | 120 | uint bal = pledgedAmount[_id][msg.sender]; 121 | pledgedAmount[_id][msg.sender] = 0; 122 | token.transfer(msg.sender, bal); 123 | 124 | emit Refund(_id, msg.sender, bal); 125 | } 126 | } -------------------------------------------------------------------------------- /contracts/MultiTierReferralSystem/test/MultiTierReferralSystem.test.ts: -------------------------------------------------------------------------------- 1 | import { loadFixture } from "@nomicfoundation/hardhat-toolbox-viem/network-helpers"; 2 | import { expect } from "chai"; 3 | import hre from "hardhat"; 4 | import { parseUnits } from "viem"; 5 | 6 | describe("Multi-tier Referral system", function () { 7 | async function deployMultiTierReferralSystem() { 8 | const [deployer, defaultUpline, account1, account2] = await hre.viem.getWalletClients(); 9 | 10 | const usdc = await hre.viem.deployContract("ExampleUSDC", []); 11 | const multiTierReferralSystem = await hre.viem.deployContract("MultiTierReferralSystem", [usdc.address, defaultUpline.account.address]); 12 | 13 | const publicClient = await hre.viem.getPublicClient(); 14 | 15 | return { 16 | deployer, 17 | defaultUpline, 18 | account1, 19 | account2, 20 | usdc, 21 | multiTierReferralSystem, 22 | publicClient, 23 | }; 24 | } 25 | 26 | describe("Deployment", function () { 27 | it("Name & Symbol", async function () { 28 | const { multiTierReferralSystem } = await loadFixture(deployMultiTierReferralSystem); 29 | 30 | expect(await multiTierReferralSystem.read.name()).to.equal("Multi-Tier Referral System"); 31 | expect(await multiTierReferralSystem.read.symbol()).to.equal("MTRS"); 32 | }); 33 | 34 | it("Default Upline & Initial Supply", async function () { 35 | const { multiTierReferralSystem, defaultUpline } = await loadFixture(deployMultiTierReferralSystem); 36 | 37 | // tokenId 1-10 is defaultUpline Account 38 | const tokenId = await multiTierReferralSystem.read.lastUplineTokenId(); 39 | expect((await multiTierReferralSystem.read.ownerOf([tokenId])).toLowerCase()).to.equal(defaultUpline.account.address); 40 | expect(await multiTierReferralSystem.read.totalSupply()).to.equal(BigInt(10)); 41 | }); 42 | }); 43 | 44 | describe("Registration", function () { 45 | it("Registration with Account 1 & Account 2", async function () { 46 | const { usdc, multiTierReferralSystem, defaultUpline, account1, account2 } = await loadFixture(deployMultiTierReferralSystem); 47 | 48 | // Check Balance USDC is 0 49 | expect(await usdc.read.balanceOf([defaultUpline.account.address])).to.equal(BigInt(0)); 50 | expect(await usdc.read.balanceOf([account1.account.address])).to.equal(BigInt(0)); 51 | expect(await usdc.read.balanceOf([account2.account.address])).to.equal(BigInt(0)); 52 | 53 | // Send 100 USDC to Account 1 & Account 2 54 | const decimalUSDC = Number(await usdc.read.decimals()); 55 | const amount = parseUnits("100", decimalUSDC); 56 | await usdc.write.transfer([account1.account.address, amount]); 57 | await usdc.write.transfer([account2.account.address, amount]); 58 | expect(await usdc.read.balanceOf([account1.account.address])).to.equal(amount); 59 | expect(await usdc.read.balanceOf([account2.account.address])).to.equal(amount); 60 | 61 | // Registration Account 1 with Default Upline 62 | await usdc.write.approve([multiTierReferralSystem.address, amount], { 63 | account: account1.account 64 | }); 65 | expect(await usdc.read.allowance([account1.account.address, multiTierReferralSystem.address])).to.equal(amount); 66 | await multiTierReferralSystem.write.registration([ 67 | BigInt(0), // Set 0 if use default upline 68 | BigInt(11) // new tokenId 69 | ], { 70 | account: account1.account 71 | }); 72 | expect(await usdc.read.balanceOf([defaultUpline.account.address])).to.equal(amount); // tokenId 1-10 distribute to defaultUpline Account -> total 100 USDC 73 | 74 | // Registration Account 2 with Account 1 (tokenId 11) 75 | await usdc.write.approve([multiTierReferralSystem.address, amount], { 76 | account: account2.account 77 | }); 78 | expect(await usdc.read.allowance([account2.account.address, multiTierReferralSystem.address])).to.equal(amount); 79 | expect((await multiTierReferralSystem.read.ownerOf([BigInt(11)])).toLowerCase()).to.equal(account1.account.address); 80 | await multiTierReferralSystem.write.registration([ 81 | BigInt(11), // Set 11 if use Upline Account 1 82 | BigInt(12) // new tokenId 83 | ], { 84 | account: account2.account 85 | }); 86 | expect(await usdc.read.balanceOf([defaultUpline.account.address])) 87 | .to.equal((amount + parseUnits("90", decimalUSDC))); // amount + (tokenId 2-10 distribute to defaultUpline Account) -> total 190 USDC 88 | expect(await usdc.read.balanceOf([account1.account.address])).to.equal(parseUnits("10", decimalUSDC)); // total 10 USDC 89 | }); 90 | }); 91 | }); 92 | -------------------------------------------------------------------------------- /contracts/erc20/tests/MyToken_hardhat_test.ts: -------------------------------------------------------------------------------- 1 | // This is an example test file. Hardhat will run every *.js file in `test/`, 2 | // so feel free to add new ones. 3 | 4 | // Hardhat tests are normally written with Mocha and Chai. 5 | 6 | // We import Chai to use its asserting functions here. 7 | const { expect } = require("chai"); 8 | 9 | // We use `loadFixture` to share common setups (or fixtures) between tests. 10 | // Using this simplifies your tests and makes them run faster, by taking 11 | // advantage of Hardhat Network's snapshot functionality. 12 | const { 13 | loadFixture, 14 | } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); 15 | const { ethers } = require("hardhat"); 16 | 17 | // `describe` is a Mocha function that allows you to organize your tests. 18 | // Having your tests organized makes debugging them easier. All Mocha 19 | // functions are available in the global scope. 20 | // 21 | // `describe` receives the name of a section of your test suite, and a 22 | // callback. The callback must define the tests of that section. This callback 23 | // can't be an async function. 24 | describe("Token contract", function () { 25 | // We define a fixture to reuse the same setup in every test. We use 26 | // loadFixture to run this setup once, snapshot that state, and reset Hardhat 27 | // Network to that snapshot in every test. 28 | async function deployTokenFixture() { 29 | // Get the Signers here. 30 | const [owner, addr1, addr2] = await ethers.getSigners(); 31 | 32 | // To deploy our contract, we just have to call ethers.deployContract and await 33 | // its waitForDeployment() method, which happens once its transaction has been 34 | // mined. 35 | const hardhatToken = await ethers.deployContract("MyToken", [owner]); 36 | 37 | await hardhatToken.waitForDeployment(); 38 | 39 | // Fixtures can return anything you consider useful for your tests 40 | return { hardhatToken, owner, addr1, addr2 }; 41 | } 42 | 43 | // You can nest describe calls to create subsections. 44 | describe("Deployment", function () { 45 | // `it` is another Mocha function. This is the one you use to define each 46 | // of your tests. It receives the test name, and a callback function. 47 | // 48 | // If the callback function is async, Mocha will `await` it. 49 | it("Should assign the total supply of tokens to the owner", async function () { 50 | const { hardhatToken, owner } = await loadFixture(deployTokenFixture); 51 | const ownerBalance = await hardhatToken.balanceOf(owner.address); 52 | expect(await hardhatToken.totalSupply()).to.equal(ownerBalance); 53 | }); 54 | }); 55 | 56 | describe("Transactions", function () { 57 | it("Should transfer tokens between accounts", async function () { 58 | const { hardhatToken, owner, addr1, addr2 } = await loadFixture( 59 | deployTokenFixture 60 | ); 61 | // Transfer 50 tokens from owner to addr1 62 | await expect( 63 | hardhatToken.transfer(addr1.address, 50) 64 | ).to.changeTokenBalances(hardhatToken, [owner, addr1], [-50, 50]); 65 | 66 | // Transfer 50 tokens from addr1 to addr2 67 | // We use .connect(signer) to send a transaction from another account 68 | await expect( 69 | hardhatToken.connect(addr1).transfer(addr2.address, 50) 70 | ).to.changeTokenBalances(hardhatToken, [addr1, addr2], [-50, 50]); 71 | }); 72 | 73 | it("Should emit Transfer events", async function () { 74 | const { hardhatToken, owner, addr1, addr2 } = await loadFixture( 75 | deployTokenFixture 76 | ); 77 | 78 | // Transfer 50 tokens from owner to addr1 79 | await expect(hardhatToken.transfer(addr1.address, 50)) 80 | .to.emit(hardhatToken, "Transfer") 81 | .withArgs(owner.address, addr1.address, 50); 82 | 83 | // Transfer 50 tokens from addr1 to addr2 84 | // We use .connect(signer) to send a transaction from another account 85 | await expect(hardhatToken.connect(addr1).transfer(addr2.address, 50)) 86 | .to.emit(hardhatToken, "Transfer") 87 | .withArgs(addr1.address, addr2.address, 50); 88 | }); 89 | 90 | it("Should fail if sender doesn't have enough tokens", async function () { 91 | const { hardhatToken, owner, addr1 } = await loadFixture( 92 | deployTokenFixture 93 | ); 94 | const initialOwnerBalance = await hardhatToken.balanceOf(owner.address); 95 | 96 | // Try to send 1 token from addr1 (0 tokens) to owner. 97 | // `require` will evaluate false and revert the transaction. 98 | await expect( 99 | hardhatToken.connect(addr1).transfer(owner.address, 1) 100 | ).to.be.reverted; 101 | 102 | // Owner balance shouldn't have changed. 103 | expect(await hardhatToken.balanceOf(owner.address)).to.equal( 104 | initialOwnerBalance 105 | ); 106 | }); 107 | }); 108 | }); -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to Klaytn DApp Toolkit contributing guide 2 | 3 | Thank you for investing your time in contributing to our project! Any contribution you make will be reflected on [https://github.com/klaytn/klaytn-dapp-toolkit](https://github.com/klaytn/klaytn-dapp-toolkit) :sparkles:. 4 | 5 | Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable. 6 | 7 | In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR. 8 | 9 | Use the table of contents icon Table of contents icon on the top left corner of this document to get to a specific section of this guide quickly. 10 | 11 | ## New contributor guide 12 | 13 | To get an overview of the project, read the [README](../README.md) file. Here are some resources to help you get started with open source contributions: 14 | 15 | - [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github) 16 | - [Set up Git](https://docs.github.com/en/get-started/getting-started-with-git/set-up-git) 17 | - [GitHub flow](https://docs.github.com/en/get-started/using-github/github-flow) 18 | - [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests) 19 | 20 | ## Getting started 21 | 22 | To navigate our codebase with confidence, see [Getting Started section](./README.md/#getting-started) :confetti_ball:. For more information on how we write our markdown files, see "[Using Markdown and Liquid in GitHub Docs](https://docs.github.com/en/contributing/writing-for-github-docs/using-markdown-and-liquid-in-github-docs)." 23 | 24 | Check to see what [types of contributions](./CONTRIBUTING.md/#types-of-contributions) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:. 25 | 26 | ### Issues 27 | 28 | #### Create a new issue 29 | 30 | If you spot a problem with the repository or want to suggest some changes, you can open an `issue` in the [Issue tab](https://github.com/klaytn/klaytn-dapp-toolkit/issues) 31 | 32 | 33 | ### Make Changes 34 | 35 | #### Make changes locally 36 | 37 | 1. Fork the repository. 38 | - Using GitHub Desktop: 39 | - [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop. 40 | - Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)! 41 | 42 | - Using the command line: 43 | - [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them. 44 | 45 | 2. Create a working branch (preferably a branch with your GitHub username) and start with your changes! 46 | 47 | ### Commit your update 48 | 49 | Commit the changes once you are happy with them :zap:. 50 | 51 | ### Pull Request 52 | 53 | When you're finished with the changes, create a pull request, also known as a PR. 54 | - Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request. 55 | - Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one. 56 | - Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge. 57 | Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request additional information. 58 | - We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch. 59 | - As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations). 60 | - If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues. 61 | 62 | ### Your PR is merged! 63 | 64 | Congratulations :tada::tada: Klaytn Foundation thanks you :sparkles:. 65 | 66 | Once your PR is merged, your contributions will be publicly visible on the [https://github.com/klaytn/klaytn-dapp-toolkit](https://github.com/klaytn/klaytn-dapp-toolkit). 67 | 68 | Now that you are part of the Klaytn OSS community, see how else you can [contribute to the OSS ecosystem](./CONTRIBUTING.md/#types-of-contributions). 69 | 70 | 71 | ## Types of contributions -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | 0x.stim@klaytn.foundation. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /klaytn-hacker-house/README.md: -------------------------------------------------------------------------------- 1 | # Klaytn Hacker House 2 | 3 | > Funding the next generation of builders on Klaytn. 4 | 5 | > [!NOTE] 6 | > Last updated: 2024-05-18. Check back regularly for new bounty tracks or updates. 7 | ## Introduction 8 | Hack, Snack, & Swag: The Ultimate Web3 Playground at Klaytn Hacker House 9 | 10 | Calling all builders, dreamers, and innovators! Get ready to ignite your Web3 journey at BUIDL Hacker House, the exciting new initiative powered by BUIDL Station, Vietnam's leading Web3 community. 11 | 12 | ## Current bounty program 13 | 14 | ### Contribute an approved smart contract 15 | Contribute an approved smart contract into [contracts library](https://github.com/klaytn/klaytn-dapp-toolkit/tree/main/contracts). 16 | 17 | #### Rewards 18 | - 50 KLAY per `merged` PR/submission 19 | 20 | #### Details 21 | - Proposed smart contract should be approved beforehand. You can open a proposal as an `issue` in the [Issue tab](https://github.com/klaytn/klaytn-dapp-toolkit/issues) 22 | - Solidity source files, scripts and test cases, a small README.md file explaining use case 23 | - Can be adopted in Remix, Hardhat or Foundry frameworks 24 | 25 | #### Submission rules 26 | - Open source 27 | - Bounty submission should be of good quality (well tested for core functionalities) 28 | 29 | --- 30 | 31 | ### Contribute an approved frontend app/component 32 | 33 | Contribute an approved frontend app into [frontend library](https://github.com/klaytn/klaytn-dapp-toolkit/tree/main/frontend). 34 | 35 | #### Rewards 36 | - 50 KLAY per `merged` PR/submission 37 | 38 | #### Details 39 | - Focus on UI/UX. So good handling of transaction lifecycle 40 | - React (w/ NextJS, Vite) or Vue 41 | - Proposed frontend should be approved beforehand. You can open a proposal as an `issue` in the [Issue tab](https://github.com/klaytn/klaytn-dapp-toolkit/issues) 42 | 43 | #### Submission rules 44 | - Open source 45 | - Bounty submission should be of good quality (well tested for core functionalities) 46 | 47 | --- 48 | 49 | ### Contribute a free to use DApp onto Cypress mainnet 50 | 51 | Contribute a free to use DApp onto mainnet 52 | 53 | #### Rewards 54 | - 500 KLAY per `merged` PR/submission 55 | 56 | #### Details 57 | - Proposed DApp should be approved beforehand. You can open a proposal as an `issue` in the [Issue tab](https://github.com/klaytn/klaytn-dapp-toolkit/issues) 58 | - Full implementation that users can use 59 | - Can be forks of popular DApp on other networks 60 | 61 | #### Ideas 62 | - Airdrop tools 63 | - NFT mint tools 64 | - POAP mint tools 65 | - Community badge mint tools 66 | - Smart contract factory 67 | 68 | #### Submission rules 69 | - Open source 70 | - Bounty submission should be of good quality (well tested for core functionalities) 71 | 72 | --- 73 | 74 | ### Contribute to Klaytn Docs 75 | 76 | Contribute to Klaytn Docs (https://docs.klaytn.foundation/) 77 | 78 | #### Rewards 79 | - 50 KLAY per `merged` PR/submission 80 | 81 | #### Details 82 | - Each PR request must improve our documentation page (more than just a typo fix) and get merged 83 | 84 | #### Rules 85 | - Open source 86 | - Bounty submission should be of good quality (well tested for core functionalities) 87 | 88 | --- 89 | 90 | ### Contribute a DApp that leverages Mint Club v2 SDK 91 | 92 | Contribute a DApp that leverages Mint Club v2 SDK 93 | 94 | #### Rewards 95 | - 500 KLAY per `merged` PR/submission 96 | 97 | #### Details 98 | - Based on the Mint Club v2 SDK (https://sdk.mint.club/) 99 | - Propose an idea beforehand on the github repo issue tab (https://github.com/klaytn/klaytn-dapp-toolkit/issues) 100 | - Full v0 implementation that users can use. Doesn't have to be completed but core functionalities should be usable. 101 | - Can be forks 102 | 103 | #### Ideas 104 | - Coin launchpad 105 | 106 | #### Rules 107 | - Open source 108 | - Bounty submission should be of good quality (well tested for core functionalities) 109 | 110 | --- 111 | ### Contribute an Open Source Developer Tool 112 | 113 | #### Rewards 114 | - 500 KLAY per `merged` PR/submission 115 | 116 | #### Details 117 | - Propose a developer tool beforehand. 118 | - Full v0 implementation that users can use. 119 | - Doesn't have to be completed but core functionalities should be usable. 120 | - Can be forks 121 | 122 | #### Ideas 123 | - Boilerplate 124 | - Educational framework 125 | - Smart contract inspector 126 | - AI solidity code assistant 127 | 128 | #### Rules 129 | - Open source 130 | - Bounty submission should be of good quality (well tested for core functionalities) 131 | 132 | --- 133 | ### Contribute a DApp/App that leverages Klaytn Fee Delegation or Role Based Account feature 134 | 135 | Contribute a DApp/App that leverages Klaytn Fee Delegation or Role Based Account feature 136 | 137 | #### Rewards 138 | - 500 KLAY per `merged` PR/submission 139 | 140 | #### Details 141 | - Proposed DApp/App should be approved beforehand. You can open a proposal as an `issue` in the [Issue tab](https://github.com/klaytn/klaytn-dapp-toolkit/issues) 142 | - Can be fullstack, backend/smart contract only, frontend only. 143 | - Bonus for adopting Go or Rust 144 | 145 | #### Rules 146 | - Open source 147 | - Bounty submission should be of good quality (well tested for core functionalities) 148 | 149 | --- 150 | ### Klaytn Educate Series(KES) 151 | 152 | Klaytn Educate Series aims to educate you on everything web3 and the Klaytn blockchain. You can register using this [link](https://lu.ma/klaytn-educate-series). 153 | 154 | #### Rewards 155 | - $100 worth of KLAY to be won 156 | 157 | #### Things to keep in mind: 158 | * Listen to the secret code in each session 159 | * Paste the secret code on the attendance site for each day (Prerequisite Download Kaikas) 160 | * Qualify for raffle only if you make 80% attendance. 161 | * Randomly share $100 worth of KLAY to qualified participants using VRF. 162 | * Contribute to open source and earn. 163 | 164 | --- 165 | ## Support 166 | If you need help with the bounty program, open a discussion in [Discussion tab](https://github.com/klaytn/klaytn-dapp-toolkit/discussions/categories/q-a) -------------------------------------------------------------------------------- /contracts/erc5115/src/abstracts/SYBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "../interfaces/IStandardizedYield.sol"; 5 | import "../libraries/TokenHelper.sol"; 6 | import "../libraries/SYUtils.sol"; 7 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 8 | import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; 9 | 10 | abstract contract SYBase is IStandardizedYield, ERC20, ReentrancyGuard, TokenHelper { 11 | address public immutable yieldToken; 12 | uint256 public yieldTokenReserve; 13 | 14 | modifier updateReserve() { 15 | _; 16 | _updateReserve(); 17 | } 18 | 19 | constructor(string memory _name, string memory _symbol, address _yieldToken) ERC20(_name, _symbol) { 20 | yieldToken = _yieldToken; 21 | } 22 | 23 | receive() external payable {} 24 | 25 | /*/////////////////////////////////////////////////////////////// 26 | DEPOSIT/REDEEM USING BASE TOKENS 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | /** 30 | * @dev See {IStandardizedYield-deposit} 31 | */ 32 | function deposit(address receiver, address tokenIn, uint256 amountTokenToPull, uint256 minSharesOut) 33 | external 34 | payable 35 | nonReentrant 36 | updateReserve 37 | returns (uint256 amountSharesOut) 38 | { 39 | require(isValidBaseToken(tokenIn), "SCY: Invalid tokenIn"); 40 | 41 | if (tokenIn == NATIVE) require(amountTokenToPull == 0, "can't pull eth"); 42 | else if (amountTokenToPull != 0) _transferIn(tokenIn, msg.sender, amountTokenToPull); 43 | 44 | uint256 amountDeposited = _getFloatingAmount(tokenIn); 45 | 46 | amountSharesOut = _deposit(tokenIn, amountDeposited); 47 | require(amountSharesOut >= minSharesOut, "insufficient out"); 48 | 49 | _mint(receiver, amountSharesOut); 50 | emit Deposit(msg.sender, receiver, tokenIn, amountDeposited, amountSharesOut); 51 | } 52 | 53 | /** 54 | * @dev See {ISuperComposableYield-redeem} 55 | */ 56 | function redeem( 57 | address receiver, 58 | uint256 amountSharesToPull, 59 | address tokenOut, 60 | uint256 minTokenOut 61 | ) external nonReentrant updateReserve returns (uint256 amountTokenOut) { 62 | require(isValidBaseToken(tokenOut), "SCY: invalid tokenOut"); 63 | 64 | if (amountSharesToPull != 0) transferFrom(msg.sender, address(this), amountSharesToPull); 65 | amountTokenOut = 0; 66 | 67 | uint256 amountSharesToRedeem = _getFloatingAmount(address(this)); 68 | 69 | amountTokenOut = _redeem(tokenOut, amountSharesToRedeem); 70 | require(amountTokenOut >= minTokenOut, "insufficient out"); 71 | 72 | _burn(address(this), amountSharesToRedeem); 73 | _transferOut(tokenOut, receiver, amountTokenOut); 74 | 75 | emit Redeem(msg.sender, receiver, tokenOut, amountSharesToRedeem, amountTokenOut); 76 | } 77 | 78 | /** 79 | * @notice mint shares based on the deposited base tokens 80 | * @param tokenIn base token address used to mint shares 81 | * @param amountDeposited amount of base tokens deposited 82 | * @return amountSharesOut amount of shares minted 83 | */ 84 | function _deposit(address tokenIn, uint256 amountDeposited) 85 | internal 86 | virtual 87 | returns (uint256 amountSharesOut); 88 | 89 | /** 90 | * @notice redeems base tokens based on amount of shares to be burned 91 | * @param tokenOut address of the base token to be redeemed 92 | * @param amountSharesToRedeem amount of shares to be burned 93 | * @return amountTokenOut amount of base tokens redeemed 94 | */ 95 | function _redeem(address tokenOut, uint256 amountSharesToRedeem) 96 | internal 97 | virtual 98 | returns (uint256 amountTokenOut); 99 | 100 | /** 101 | * @notice updates the amount of yield token reserves in this contract 102 | */ 103 | function _updateReserve() internal virtual { 104 | yieldTokenReserve = _selfBalance(yieldToken); 105 | } 106 | 107 | /** 108 | * @notice returns the amount of unprocessed tokens owned by this contract 109 | * @param token address of the token to be queried 110 | */ 111 | function _getFloatingAmount(address token) internal view virtual returns (uint256) { 112 | if (token != yieldToken) return _selfBalance(token); 113 | return _selfBalance(token) - yieldTokenReserve; 114 | } 115 | 116 | /*/////////////////////////////////////////////////////////////// 117 | EXCHANGE-RATE 118 | //////////////////////////////////////////////////////////////*/ 119 | 120 | /** 121 | * @dev See {IStandardizedYield-exchangeRateCurrent} 122 | */ 123 | function exchangeRateCurrent() external virtual override returns (uint256 res); 124 | 125 | /** 126 | * @dev See {IStandardizedYield-exchangeRateStored} 127 | */ 128 | function exchangeRateStored() external view virtual override returns (uint256 res); 129 | 130 | /*/////////////////////////////////////////////////////////////// 131 | REWARDS-RELATED 132 | //////////////////////////////////////////////////////////////*/ 133 | 134 | /** 135 | * @dev See {IStandardizedYield-claimRewards} 136 | */ 137 | function claimRewards(address /*user*/ ) external virtual override returns (uint256[] memory rewardAmounts) { 138 | rewardAmounts = new uint256[](0); 139 | } 140 | 141 | /** 142 | * @dev See {IStandardizedYield-getRewardTokens} 143 | */ 144 | function getRewardTokens() external view virtual override returns (address[] memory rewardTokens) { 145 | rewardTokens = new address[](0); 146 | } 147 | 148 | /** 149 | * @dev See {IStandardizedYield-accruredRewards} 150 | */ 151 | function accruedRewards(address /*user*/ ) 152 | external 153 | view 154 | virtual 155 | override 156 | returns (uint256[] memory rewardAmounts) 157 | { 158 | rewardAmounts = new uint256[](0); 159 | } 160 | 161 | /** 162 | * @notice See {IStandardizedYield-decimals} 163 | */ 164 | function decimals() public view virtual override(ERC20, IERC20Metadata) returns (uint8) { 165 | return 18; 166 | } 167 | 168 | /** 169 | * @notice See {IStandardizedYield-getBaseTokens} 170 | */ 171 | function getBaseTokens() external view virtual override returns (address[] memory res); 172 | 173 | /** 174 | * @dev See {IStandardizedYield-isValidBaseToken} 175 | */ 176 | function isValidBaseToken(address token) public view virtual override returns (bool); 177 | } 178 | -------------------------------------------------------------------------------- /contracts/erc5115/src/interfaces/IStandardizedYield.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.20; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 5 | 6 | interface IStandardizedYield is IERC20Metadata { 7 | /// @dev Emitted whenever the exchangeRate is updated 8 | event ExchangeRateUpdated(uint256 oldExchangeRate, uint256 newExchangeRate); 9 | 10 | /// @dev Emitted when any base tokens is deposited to mint shares 11 | event Deposit( 12 | address indexed caller, 13 | address indexed receiver, 14 | address indexed tokenIn, 15 | uint256 amountDeposited, 16 | uint256 amountSYOut 17 | ); 18 | 19 | /// @dev Emitted when any shares are redeemed for base tokens 20 | event Redeem( 21 | address indexed caller, 22 | address indexed receiver, 23 | address indexed tokenOut, 24 | uint256 amountSYToRedeem, 25 | uint256 amountTokenOut 26 | ); 27 | 28 | enum AssetType { 29 | TOKEN, 30 | LIQUIDITY 31 | } 32 | 33 | /// @dev Emitted when (`user`) claims their rewards 34 | event ClaimRewards( 35 | address indexed user, 36 | address[] rewardTokens, 37 | uint256[] rewardAmounts 38 | ); 39 | 40 | /** 41 | * @notice mints an amount of shares by depositing a base token. 42 | * @param receiver shares recipient address 43 | * @param tokenIn address of the base tokens to mint shares 44 | * @param amountTokenToPull amount of base tokens to be transferred from (`msg.sender`) 45 | * @param minSharesOut reverts if amount of shares minted is lower than this 46 | * @return amountSharesOut amount of shares minted 47 | * @dev 48 | * 49 | * This contract receives base tokens using these two (possibly both) methods: 50 | * - The tokens have been transferred directly to this contract prior to calling deposit(). 51 | * - Exactly `amountTokenToPull` are transferred to this contract using `transferFrom()` upon calling deposit(). 52 | * 53 | * The amount of shares minted will be based on the combined amount of base tokens deposited 54 | * using the given two methods. 55 | * 56 | * Emits a {Deposit} event 57 | * 58 | * Requirements: 59 | * - (`baseTokenIn`) must be a valid base token. 60 | * - There must be an ongoing approval from (`msg.sender`) for this contract with 61 | * at least `amountTokenToPull` base tokens. 62 | */ 63 | function deposit( 64 | address receiver, 65 | address tokenIn, 66 | uint256 amountTokenToPull, 67 | uint256 minSharesOut 68 | ) external payable returns (uint256 amountSharesOut); 69 | 70 | /** 71 | * @notice redeems an amount of base tokens by burning some shares 72 | * @param receiver recipient address 73 | * @param amountSharesToPull amount of shares to be transferred from (`msg.sender`) 74 | * @param tokenOut address of the base token to be redeemed 75 | * @param minTokenOut reverts if amount of base token redeemed is lower than this 76 | * @return amountTokenOut amount of base tokens redeemed 77 | * @dev 78 | * 79 | * This contract receives shares using these two (possibly both) methods: 80 | * - The shares have been transferred directly to this contract prior to calling redeem(). 81 | * - Exactly `amountSharesToPull` are transferred to this contract using `transferFrom()` upon calling redeem(). 82 | * 83 | * The amount of base tokens redeemed based on the combined amount of shares deposited 84 | * using the given two methods 85 | * 86 | * Emits a {Redeem} event 87 | * 88 | * Requirements: 89 | * - (`tokenOut`) must be a valid base token. 90 | * - There must be an ongoing approval from (`msg.sender`) for this contract with 91 | * at least `amountSharesToPull` shares. 92 | */ 93 | function redeem( 94 | address receiver, 95 | uint256 amountSharesToPull, 96 | address tokenOut, 97 | uint256 minTokenOut 98 | ) external returns (uint256 amountTokenOut); 99 | 100 | /** 101 | * @notice exchangeRateCurrent * scyBalance / 1e18 must return the asset balance of the account 102 | * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of scy 103 | he can mint must be X * exchangeRateCurrent / 1e18 104 | * @dev SCYUtils's assetToScy & scyToAsset should be used instead of raw multiplication 105 | & division 106 | * 107 | * May emit a {NewExchangeRate} event 108 | */ 109 | function exchangeRateCurrent() external returns (uint256 res); 110 | 111 | /** 112 | * @notice returns the previously updated and stored shares exchange rate 113 | * @dev the returned value may be outdated if exchangeRateCurrent() was not called for a 114 | * extended period of time 115 | */ 116 | function exchangeRateStored() external view returns (uint256 res); 117 | 118 | /** 119 | * @notice claims reward for (`user`) 120 | * @param user the user receiving their rewards 121 | * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens` 122 | * @dev 123 | * Emits a `ClaimRewardss` event 124 | * See {getRewardTokens} for list of reward tokens 125 | */ 126 | function claimRewards( 127 | address user 128 | ) external returns (uint256[] memory rewardAmounts); 129 | 130 | /** 131 | * @notice get the amount of unclaimed rewards for (`user`) 132 | * @param user the user to check for 133 | * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens` 134 | */ 135 | function accruedRewards( 136 | address user 137 | ) external view returns (uint256[] memory rewardAmounts); 138 | 139 | /** 140 | * @notice returns the list of reward token addresses 141 | */ 142 | function getRewardTokens() external view returns (address[] memory); 143 | 144 | /** 145 | * @notice returns the address of the underlying yield token 146 | */ 147 | function yieldToken() external view returns (address); 148 | 149 | /** 150 | * @notice returns a list of all the base tokens that can be deposited to mint shares 151 | */ 152 | function getBaseTokens() external view returns (address[] memory res); 153 | 154 | /** 155 | * @notice checks whether a token is a valid base token 156 | * @notice returns a boolean indicating whether this is a valid token 157 | */ 158 | function isValidBaseToken(address token) external view returns (bool); 159 | 160 | /** 161 | * @notice This function contains information to interpret what the asset is 162 | * @notice decimals is the decimals to format asset balances 163 | * @notice if asset is an ERC20 token, assetType = 0, assetAddress is the address of the token 164 | * @notice if asset is liquidity of an AMM (like sqrt(k) in UniswapV2 forks), assetType = 1, 165 | assetAddress is the address of the LP token 166 | * @notice assetDecimals is the decimals of the asset 167 | */ 168 | function assetInfo() 169 | external 170 | view 171 | returns ( 172 | AssetType assetType, 173 | address assetAddress, 174 | uint8 assetDecimals 175 | ); 176 | } 177 | -------------------------------------------------------------------------------- /contracts/ContriBoost/contracts/Contribute.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.19; 3 | 4 | import "@klaytn/contracts/token/ERC20/IERC20.sol"; 5 | import { VRFConsumerBase } from "@bisonai/orakl-contracts/src/v0.1/VRFConsumerBase.sol"; 6 | import { IVRFCoordinator } from "@bisonai/orakl-contracts/src/v0.1/interfaces/IVRFCoordinator.sol"; 7 | 8 | contract ContributionSystem is VRFConsumerBase { 9 | // Structure to define a participant 10 | struct Participant { 11 | uint id; // Unique identifier for the participant 12 | uint depositAmount; // Amount deposited by the participant 13 | uint lastDepositTime; // Time of the last deposit made by the participant 14 | bool exists; // Flag to check if participant exists 15 | bool receivedFunds; // Flag to check if the participant has received funds 16 | } 17 | 18 | address public host; // Address of the contract deployer 19 | uint public dayRange; // Duration of each segment in days 20 | uint public expectedNumber; // Expected number of participants 21 | uint public currentSegment; // Current segment 22 | uint public contributionAmount; // Expected amount each participant should contribute 23 | address public tokenAddress; // Address of the ERC20 token used for contributions 24 | mapping(address => Participant) public participants; // Mapping of participant addresses to their Participant struct 25 | address[] public participantList; // Array to store addresses of all participants 26 | uint public totalAmount; // Total amount of tokens in the contract 27 | 28 | // Events 29 | event Deposit(address indexed participant, uint amount); 30 | event FundsTransferred(address indexed from, address indexed to, uint amount); 31 | event SegmentEnd(uint segmentNumber); 32 | event RandomNumberGenerated(uint256 randomNumber); 33 | 34 | IVRFCoordinator private COORDINATOR; // Instance of the VRF Coordinator 35 | bytes32 private keyHash; // Key hash for VRF request 36 | uint256 private fee; // Fee required to make a request 37 | uint256 public sRandomWord; // Random number generated by VRF 38 | 39 | // Constructor 40 | constructor( 41 | address coordinator, 42 | bytes32 _keyHash, 43 | uint256 _fee, 44 | uint _dayRange, 45 | uint _expectedNumber, 46 | uint _contributionAmount, 47 | address _tokenAddress 48 | ) VRFConsumerBase(coordinator) { 49 | host = msg.sender; 50 | dayRange = _dayRange; 51 | expectedNumber = _expectedNumber; 52 | contributionAmount = _contributionAmount; 53 | tokenAddress = _tokenAddress; // Initialize token address 54 | currentSegment = 1; 55 | COORDINATOR = IVRFCoordinator(coordinator); 56 | keyHash = _keyHash; 57 | fee = _fee; 58 | totalAmount = IERC20(tokenAddress).balanceOf(address(this)); // Update total amount 59 | } 60 | 61 | // Modifier: Only host 62 | modifier onlyHost() { 63 | require(msg.sender == host, "Only the host can call this function"); 64 | _; 65 | } 66 | 67 | // Modifier: Can join 68 | modifier canJoin() { 69 | require(!participants[msg.sender].exists, "You are already a participant"); 70 | _; 71 | } 72 | 73 | // Allow participants to join the system 74 | function join() external payable canJoin { 75 | Participant storage participant = participants[msg.sender]; 76 | participant.id = participantList.length + 1; 77 | participant.exists = true; 78 | participantList.push(msg.sender); 79 | emit Deposit(msg.sender, msg.value); 80 | } 81 | 82 | // Allow participants to deposit funds into the contract 83 | function deposit(uint _amount) external { 84 | Participant storage participant = participants[msg.sender]; 85 | require(participant.exists, "You are not a participant"); 86 | require(block.timestamp >= participant.lastDepositTime + dayRange * 1 days, "You can only deposit once per segment"); 87 | 88 | // Transfer tokens from sender to contract 89 | require(IERC20(tokenAddress).transferFrom(msg.sender, address(this), _amount), "Token transfer failed"); 90 | require(_amount == contributionAmount, "Please send the exact deposit amount"); 91 | 92 | participant.depositAmount += _amount; 93 | participant.lastDepositTime = block.timestamp; 94 | emit Deposit(msg.sender, _amount); 95 | } 96 | 97 | // Distribute funds to a random participant at the end of each segment 98 | function distributeFunds() external onlyHost { 99 | require(participantList.length == expectedNumber, "Expected number of participants not reached"); 100 | require(currentSegment <= expectedNumber, "All segments have been completed"); 101 | 102 | // Calculate 2% share for the host 103 | uint hostShare = totalAmount * 2 / 100; 104 | payable(msg.sender).transfer(hostShare); 105 | 106 | // Deduct host share from the total amount 107 | totalAmount -= hostShare; 108 | 109 | // Request a random number from the VRF Coordinator 110 | requestRandomWords(keyHash, 0, 300000, 1); 111 | } 112 | 113 | // Request a random number from the VRF Coordinator 114 | function requestRandomWords( 115 | bytes32 _keyHash, 116 | uint64 _accId, 117 | uint32 _callbackGasLimit, 118 | uint32 _numWords 119 | ) public returns (uint256 requestId) { 120 | requestId = COORDINATOR.requestRandomWords(_keyHash, _accId, _callbackGasLimit, _numWords); 121 | } 122 | 123 | // Callback function that fulfills the random number request and transfers funds to the randomly chosen participant 124 | function fulfillRandomWords(uint256 /* requestId */, uint256[] memory _randomWords) internal override { 125 | sRandomWord = _randomWords[0]; 126 | // Select a random participant who hasn't received funds yet 127 | address randomParticipant = participantList[sRandomWord % participantList.length]; 128 | while (participants[randomParticipant].receivedFunds) { 129 | randomParticipant = participantList[sRandomWord % participantList.length]; 130 | } 131 | 132 | // Transfer remaining funds to the random participant 133 | require(IERC20(tokenAddress).transfer(randomParticipant, totalAmount), "Token transfer failed"); 134 | participants[randomParticipant].receivedFunds = true; 135 | emit FundsTransferred(address(this), randomParticipant, totalAmount); 136 | 137 | // Increment segment count 138 | currentSegment++; 139 | 140 | // If all segments have been completed, reset segment count and emit event 141 | if (currentSegment > expectedNumber) { 142 | currentSegment = 1; 143 | emit SegmentEnd(expectedNumber); 144 | } 145 | } 146 | 147 | // Returns a random participant from the participantList 148 | function getRandomParticipant() internal view returns (address) { 149 | uint randIndex = uint(keccak256(abi.encodePacked(block.timestamp, block.difficulty, blockhash(block.number - 1)))) % participantList.length; 150 | return participantList[randIndex]; 151 | } 152 | 153 | // Allow the contract host to withdraw remaining funds 154 | function withdraw() external onlyHost { 155 | require(IERC20(tokenAddress).transfer(host, totalAmount), "Token transfer failed"); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /contracts/gaslite-airdrop/contracts/GasliteDrop.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.19; 2 | 3 | /** 4 | 5 | bbbbbbbb dddddddd 6 | b::::::b d::::::d 7 | b::::::b d::::::d 8 | b::::::b d::::::d 9 | b:::::b d:::::d 10 | ggggggggg ggggg aaaaaaaaaaaaa ssssssssss b:::::bbbbbbbbb aaaaaaaaaaaaa ddddddddd:::::d 11 | g:::::::::ggg::::g a::::::::::::a ss::::::::::s b::::::::::::::bb a::::::::::::a dd::::::::::::::d 12 | g:::::::::::::::::g aaaaaaaaa:::::ass:::::::::::::s b::::::::::::::::b aaaaaaaaa:::::a d::::::::::::::::d 13 | g::::::ggggg::::::gg a::::as::::::ssss:::::s b:::::bbbbb:::::::b a::::ad:::::::ddddd:::::d 14 | g:::::g g:::::g aaaaaaa:::::a s:::::s ssssss b:::::b b::::::b aaaaaaa:::::ad::::::d d:::::d 15 | g:::::g g:::::g aa::::::::::::a s::::::s b:::::b b:::::b aa::::::::::::ad:::::d d:::::d 16 | g:::::g g:::::g a::::aaaa::::::a s::::::s b:::::b b:::::b a::::aaaa::::::ad:::::d d:::::d 17 | g::::::g g:::::ga::::a a:::::assssss s:::::s b:::::b b:::::ba::::a a:::::ad:::::d d:::::d 18 | g:::::::ggggg:::::ga::::a a:::::as:::::ssss::::::s b:::::bbbbbb::::::ba::::a a:::::ad::::::ddddd::::::dd 19 | g::::::::::::::::ga:::::aaaa::::::as::::::::::::::s b::::::::::::::::b a:::::aaaa::::::a d:::::::::::::::::d 20 | gg::::::::::::::g a::::::::::aa:::as:::::::::::ss b:::::::::::::::b a::::::::::aa:::a d:::::::::ddd::::d 21 | gggggggg::::::g aaaaaaaaaa aaaa sssssssssss bbbbbbbbbbbbbbbb aaaaaaaaaa aaaa ddddddddd ddddd 22 | g:::::g 23 | gggggg g:::::g 24 | g:::::gg gg:::::g 25 | g::::::ggg:::::::g 26 | gg:::::::::::::g 27 | ggg::::::ggg 28 | gggggg 29 | */ 30 | 31 | /** 32 | * @title GasliteDrop 33 | * @notice Turbo gas optimized bulk transfers of ERC20, ERC721, and ETH 34 | * @author Harrison (@PopPunkOnChain) 35 | * @author Gaslite (@GasliteGG) 36 | * @author Pop Punk LLC (@PopPunkLLC) 37 | */ 38 | contract GasliteDrop { 39 | 40 | /** 41 | * @notice Airdrop ERC721 tokens to a list of addresses 42 | * @param _nft The address of the ERC721 contract 43 | * @param _addresses The addresses to airdrop to 44 | * @param _tokenIds The tokenIds to airdrop 45 | */ 46 | function airdropERC721( 47 | address _nft, 48 | address[] calldata _addresses, 49 | uint256[] calldata _tokenIds 50 | ) external payable { 51 | assembly { 52 | // Check that the number of addresses matches the number of tokenIds 53 | if iszero(eq(_tokenIds.length, _addresses.length)) { 54 | revert(0, 0) 55 | } 56 | // transferFrom(address from, address to, uint256 tokenId) 57 | mstore(0x00, hex"23b872dd") 58 | // from address 59 | mstore(0x04, caller()) 60 | 61 | // end of array 62 | let end := add(_addresses.offset, shl(5, _addresses.length)) 63 | // diff = _addresses.offset - _tokenIds.offset 64 | let diff := sub(_addresses.offset, _tokenIds.offset) 65 | 66 | // Loop through the addresses 67 | for { let addressOffset := _addresses.offset } 1 {} { 68 | // to address 69 | mstore(0x24, calldataload(addressOffset)) 70 | // tokenId 71 | mstore(0x44, calldataload(sub(addressOffset, diff))) 72 | // transfer the token 73 | if iszero(call(gas(), _nft, 0, 0x00, 0x64, 0, 0)){ 74 | revert(0, 0) 75 | } 76 | // increment the address offset 77 | addressOffset := add(addressOffset, 0x20) 78 | // if addressOffset >= end, break 79 | if iszero(lt(addressOffset, end)) { break } 80 | } 81 | } 82 | } 83 | 84 | /** 85 | * @notice Airdrop ERC20 tokens to a list of addresses 86 | * @param _token The address of the ERC20 contract 87 | * @param _addresses The addresses to airdrop to 88 | * @param _amounts The amounts to airdrop 89 | * @param _totalAmount The total amount to airdrop 90 | */ 91 | function airdropERC20( 92 | address _token, 93 | address[] calldata _addresses, 94 | uint256[] calldata _amounts, 95 | uint256 _totalAmount 96 | ) external payable { 97 | assembly { 98 | // Check that the number of addresses matches the number of amounts 99 | if iszero(eq(_amounts.length, _addresses.length)) { 100 | revert(0, 0) 101 | } 102 | 103 | // transferFrom(address from, address to, uint256 amount) 104 | mstore(0x00, hex"23b872dd") 105 | // from address 106 | mstore(0x04, caller()) 107 | // to address (this contract) 108 | mstore(0x24, address()) 109 | // total amount 110 | mstore(0x44, _totalAmount) 111 | 112 | // transfer total amount to this contract 113 | if iszero(call(gas(), _token, 0, 0x00, 0x64, 0, 0)){ 114 | revert(0, 0) 115 | } 116 | 117 | // transfer(address to, uint256 value) 118 | mstore(0x00, hex"a9059cbb") 119 | 120 | // end of array 121 | let end := add(_addresses.offset, shl(5, _addresses.length)) 122 | // diff = _addresses.offset - _amounts.offset 123 | let diff := sub(_addresses.offset, _amounts.offset) 124 | 125 | // Loop through the addresses 126 | for { let addressOffset := _addresses.offset } 1 {} { 127 | // to address 128 | mstore(0x04, calldataload(addressOffset)) 129 | // amount 130 | mstore(0x24, calldataload(sub(addressOffset, diff))) 131 | // transfer the tokens 132 | if iszero(call(gas(), _token, 0, 0x00, 0x64, 0, 0)){ 133 | revert(0, 0) 134 | } 135 | // increment the address offset 136 | addressOffset := add(addressOffset, 0x20) 137 | // if addressOffset >= end, break 138 | if iszero(lt(addressOffset, end)) { break } 139 | } 140 | } 141 | } 142 | 143 | /** 144 | * @notice Airdrop ETH to a list of addresses 145 | * @param _addresses The addresses to airdrop to 146 | * @param _amounts The amounts to airdrop 147 | */ 148 | function airdropETH( 149 | address[] calldata _addresses, 150 | uint256[] calldata _amounts 151 | ) external payable { 152 | assembly { 153 | // Check that the number of addresses matches the number of amounts 154 | if iszero(eq(_amounts.length, _addresses.length)) { 155 | revert(0, 0) 156 | } 157 | 158 | // iterator 159 | let i := _addresses.offset 160 | // end of array 161 | let end := add(i, shl(5, _addresses.length)) 162 | // diff = _addresses.offset - _amounts.offset 163 | let diff := sub(_amounts.offset, _addresses.offset) 164 | 165 | // Loop through the addresses 166 | for {} 1 {} { 167 | // transfer the ETH 168 | if iszero( 169 | call(gas(), calldataload(i), calldataload(add(i, diff)), 0x00, 0x00, 0x00, 0x00) 170 | ) { revert(0x00, 0x00) } 171 | // increment the iterator 172 | i := add(i, 0x20) 173 | // if i >= end, break 174 | if eq(end, i) { break } 175 | } 176 | } 177 | } 178 | } --------------------------------------------------------------------------------