├── 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 | [](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 | 
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 | [37m[40m@openzeppelin/test-helpers[49m[39m [30m[43mWARN[49m[39m 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 | | [90mSolc version: 0.8.0[39m · [90mOptimizer enabled: false[39m · [90mRuns: 200[39m · [90mBlock limit: 30000000 gas[39m │
24 | ··············································|····························|·············|······························
25 | | [32m[1mMethods[22m[39m │
26 | ····················|·························|··············|·············|·············|···············|··············
27 | | [1mContract[22m · [1mMethod[22m · [32mMin[39m · [32mMax[39m · [32mAvg[39m · [1m# calls[22m · [1meur (avg)[22m │
28 | ····················|·························|··············|·············|·············|···············|··············
29 | | [90mERC20Mock[39m · mint · [36m51505[39m · [31m68617[39m · 66716 · [90m9[39m · [32m[90m-[32m[39m │
30 | ····················|·························|··············|·············|·············|···············|··············
31 | | [90mFlashBorrower[39m · flashBorrow · [36m109344[39m · [31m185991[39m · 161025 · [90m5[39m · [32m[90m-[32m[39m │
32 | ····················|·························|··············|·············|·············|···············|··············
33 | | [90mFlashBorrower[39m · flashBorrowAndReenter · [36m194092[39m · [31m198089[39m · 196091 · [90m2[39m · [32m[90m-[32m[39m │
34 | ····················|·························|··············|·············|·············|···············|··············
35 | | [90mFlashMinterMock[39m · mint · - · - · 68672 · [90m1[39m · [32m[90m-[32m[39m │
36 | ····················|·························|··············|·············|·············|···············|··············
37 | | [32m[1mDeployments[22m[39m · · [1m% of limit[22m · │
38 | ··············································|··············|·············|·············|···············|··············
39 | | ERC20Mock · [36m921125[39m · [31m921149[39m · 921137 · [90m3.1 %[39m · [32m[90m-[32m[39m │
40 | ··············································|··············|·············|·············|···············|··············
41 | | FlashBorrower · [36m1078594[39m · [31m1078606[39m · 1078605 · [90m3.6 %[39m · [32m[90m-[32m[39m │
42 | ··············································|··············|·············|·············|···············|··············
43 | | FlashLender · [36m936681[39m · [31m936693[39m · 936690 · [90m3.1 %[39m · [32m[90m-[32m[39m │
44 | ··············································|··············|·············|·············|···············|··············
45 | | FlashMinterMock · - · - · 1567090 · [90m5.2 %[39m · [32m[90m-[32m[39m │
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
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 | }
--------------------------------------------------------------------------------