# 模擬考試題 - JoeHo
**及格線:6題/10題**
## [](https://hackmd.io/@intheblack/By_Bmg7qq#Solidity-%E5%9F%BA%E7%A4%8E "Solidity-基礎")Solidity 基礎
**1. 列舉五種 Solidity 的型別並且寫出實際例子**
- Integer:
- `uint8 public test = 168;`
- Boolean:
- `bool private isDone = true;`
- String:
- `string public testString = "test";`
- Address:
- `address addr1 = msg.sender;`
- `address public myAddress = address(0xB42faBF7BCAE8bc5E368716B568a6f8Fdf3F84ec);`
- bytes:
- `bytes32 private test="test";`
**2. 寫出一 function 可接受 eth value 並且 return 自定義結果**
```
function getEth(uint256 memory value) public pure returns (String memory){
return "I got money!";
}
```
**3. ERC20 合約部屬至 rinkeby,寫上部屬的合約地址**
- contract:
- https://rinkeby.etherscan.io/address/0xe6b4b6002d4f5d9e865751d9fdc2ea1c797ecb39
- transaction:
- https://rinkeby.etherscan.io/tx/0xfd62d20ceecadd26c69d23e5f342616e3c197709b4453f2c77e0442830f792c0
- contract code:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
```
## [Solidity 進階](https://hackmd.io/@intheblack/By_Bmg7qq#Solidity-%E9%80%B2%E9%9A%8E "Solidity-進階")
**1. 以文字描述為智能合約增加流動性的流程**
- 加入 staking
- ex. 如何在 pancake 為代幣/contract 添加流動性
**2. 實作 ERC20 質押某代幣,timelock(固定鎖倉期,自定義), reward (回饋該代幣)**
- reference
- https://hackmd.io/aaWn-YrtQsuXKTBEsjcOaw?view
- explain
- 需要 reward 原質押代幣
- 質押 USDT 要能夠 reward USDT
- 用 week3 homework 的 basic 加上 reward 原代幣
## [Solidity 整合開發相關](https://hackmd.io/@intheblack/By_Bmg7qq#Solidity-%E6%95%B4%E5%90%88%E9%96%8B%E7%99%BC%E7%9B%B8%E9%97%9C "Solidity-整合開發相關")
**1. 試說明如何整合 VSCode, 以及 Remix 的開發環境**
- 在 remix 上有 connect localhost
- 使用 vs code extension
- https://github.com/ethereum/remix-vscode
- https://medium.com/remix-ide/a-remix-ide-extension-for-vscode-1f751fdeee46
- Ethereum Remix
- https://marketplace.visualstudio.com/items?itemName=RemixProject.ethereum-remix
**2. 試寫出 contract auto verify 的 相關內容(npm install xxx, hardhat.config.js, npm hardhat xxx)**
- reference
- https://moralis.io/how-to-verify-a-smart-contract-with-hardhat/
- https://www.youtube.com/watch?v=h05-TkWPCvA
- https://morioh.com/p/e395b47eb0b6
- ...
- https://docs.avax.network/dapps/smart-contracts/verify-smart-contract-using-hardhat-and-snowtrace
- https://docs.etherscan.io/tutorials/verifying-contracts-programmatically
- Verifying Contracts Programmatically
- https://ethereum.stackexchange.com/questions/126815/automatic-verification-of-smart-contracts-deployed-from-another-smart-contract
- Automatic verification of Smart Contracts deployed from another Smart Contract
-
- Ans:
- ...
```solidity
npm install hardhat
npm install @openzeppelin/contracts
// create ERC20 contract
npx hardhat compile
// create hardhat deployment script
// verify smart contract
npm install @openzeppelin/hardhat-etherscan
// OR
// npm install --save-dev @nomiclabs/hardhat-etherscan
// require("@nomiclabs/hardhat-etherscan");
npx hardhat run scripts/deploy.js --network ropsten
npx hardhat verify "ADDRESS" --network ropsten
```
```
// hardhat.config.js
require("@nomiclabs/hardhat-etherscan");
module.exports = {
networks: {
mainnet: { ... }
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: "YOUR_ETHERSCAN_API_KEY"
}
};
```
**3. 試寫出部屬 ERC721 合約並且先 mint 10 個 NFT 的 hardhat.js script**
```
## hardhat.config.js
/**
* @type import(‘hardhat/config’).HardhatUserConfig
*/
require(“dotenv”).config();
require(“@nomiclabs/hardhat-ethers”);
const { API_URL, PRIVATE_KEY } = process.env;
module.exports = {
solidity: “0.8.9”,
defaultNetwork: “mumbai”,
networks: {
hardhat: {},
mumbai: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`],
},
},
```
- reference
- https://coinsbench.com/erc-721-nft-smart-contract-deployment-using-hardhat-97c74ce1362a
## [Solidity 資安相關](https://hackmd.io/@intheblack/By_Bmg7qq#Solidity-%E8%B3%87%E5%AE%89%E7%9B%B8%E9%97%9C "Solidity-資安相關")
**標註程式碼第幾行可能有資安問題,並說明何種資安問題,並提出解法**
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract DepositContract {
using SafeMath for uint256;
mapping(address => uint256) public balance;
function deposit() external payable {
balance[msg.sender] += msg.value;
}
function withdraw(uint256 amount) external {
require(balance[msg.sender] >= amount, "Account balance is not enough");
balance[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed.");
}
function withdrawAll() external {
(bool success, ) = msg.sender.call{value: balance[msg.sender]}("");
require(success, "Transfer failed.");
balance[msg.sender] = 0;
}
}
```
- Ans
-
- ...
- reference
- https://solidity-by-example.org/hacks/re-entrancy
- 攻擊者可設置攻擊合約,
- withdraw() 此函式裡的 `(bool sent, ) = msg.sender.call{value: bal}("");` 由於未設置
- https://ethereum.stackexchange.com/questions/118859/what-is-returned-from-msg-sender-callvalue-amount
- The low level Solidity method call performs a call to a contract and returns if this call was successful and the data it returns.
- https://ethereum.stackexchange.com/questions/42521/what-does-msg-sender-call-do-in-solidity
- msg.sender.call() calls the fallback-function on msg.sender.
-
## [Solidity 節省 Gasfee 相關](https://hackmd.io/@intheblack/By_Bmg7qq#Solidity-%E7%AF%80%E7%9C%81-Gasfee-%E7%9B%B8%E9%97%9C "Solidity-節省-Gasfee-相關")
**嘗試閱讀以下程式碼,如何寫出更節省Gas fee 的方法**
```solidity
...
...
address[] whitelistedAddresses;
function isWhitelisted(address _user) public view returns (bool) {
for (uint i = 0; i < whitelistedAddresses.length; i++) {
if (whitelistedAddresses[i] == _user) {
return true;
}
}
return false;
}
```
- Ans:
- use mapping, avoid for loop
-
**完整程式碼**
[https://etherscan.io/address/0xae122962331c2b02f837b2aa501d3c5d903ed28a#code](https://etherscan.io/address/0xae122962331c2b02f837b2aa501d3c5d903ed28a#code)