Skip to content

Commit

Permalink
Merge pull request #13 from AmazingAng/main
Browse files Browse the repository at this point in the history
merge from current
  • Loading branch information
AmazingAng authored Jan 30, 2024
2 parents e0d6430 + d278fd8 commit e351480
Show file tree
Hide file tree
Showing 126 changed files with 6,053 additions and 76 deletions.
1 change: 1 addition & 0 deletions 02_ValueTypes/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ bool public _bool5 = _bool != _bool1; // 不相等
在上述代码中:变量 `_bool` 的取值是 `true``_bool1``_bool` 的非,为 `false``_bool && _bool1``false``_bool || _bool1``true``_bool == _bool1``false``_bool != _bool1``true`

**值得注意的是:**`&&``||` 运算符遵循短路规则,这意味着,假如存在 `f(x) || g(y)` 的表达式,如果 `f(x)``true``g(y)` 不会被计算,即使它和 `f(x)` 的结果是相反的。假如存在`f(x) && g(y)` 的表达式,如果 `f(x)``false``g(y)` 不会被计算。
所谓“短路规则”,一般出现在逻辑与(&&)和逻辑或(||)中。 当逻辑或(&&)的第一个条件为false时,就不会再去判断第二个条件; 当逻辑与(||)的第一个条件为true时,就不会再去判断第二个条件,这就是短路规则。

### 2. 整型

Expand Down
2 changes: 1 addition & 1 deletion 35_DutchAuction/DutchAuction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract DutchAuction is Ownable, ERC721 {
uint256[] private _allTokens; // 记录所有存在的tokenId

//设定拍卖起始时间:我们在构造函数中会声明当前区块时间为起始时间,项目方也可以通过`setAuctionStartTime(uint32)`函数来调整
constructor() ERC721("WTF Dutch Auctoin", "WTF Dutch Auctoin") {
constructor() Ownable(msg.sender) ERC721("WTF Dutch Auction", "WTF Dutch Auction") {
auctionStartTime = block.timestamp;
}

Expand Down
3 changes: 2 additions & 1 deletion 45_Timelock/Timelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ contract Timelock{
if (bytes(signature).length == 0) {
callData = data;
} else {
// 这里如果采用encodeWithSignature的编码方式来实现调用管理员的函数,请将参数data的类型改为address。不然会导致管理员的值变为类似"0x0000000000000000000000000000000000000020"的值。其中的0x20是代表字节数组长度的意思.
callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
}
// 利用call执行交易
Expand Down Expand Up @@ -139,4 +140,4 @@ contract Timelock{
) public pure returns (bytes32) {
return keccak256(abi.encode(target, value, signature, data, executeTime));
}
}
}
6 changes: 3 additions & 3 deletions Languages/en/23_Delegatecall_en/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Codes and tutorials are open source on GitHub: [github.com/AmazingAng/WTFSolidit
-----

## `delegatecall`
`delegatecall` is similar to `call`, is a low level function in `Solidity`. `delegate` meas entrust/represent, so what does `delegatecall`entrust?
`delegatecall` is similar to `call`, is a low level function in `Solidity`. `delegate` means entrust/represent, so what does `delegatecall` entrust?

When user `A` `call` contract `C` via contract `B`, the executed functions are from contract `C`, the `execution context` (the environment including state and variable) is in contract `C`: `msg.sender` is contract `B`'s address, and if state variables are changed due to function call, the affected state variables are in contract `C`.

Expand All @@ -47,7 +47,7 @@ abi.encodeWithSignature("function signature", parameters separated by comma)

Unlike `call`, `delegatecall` can specify the value of `gas` when calling smart contract, but the value of `ETH` can't be specified.

> **Attention**: using delegatecall could incur risk, make sure the storage layout of state variables of current contract and target cotnract is same, and target contract is safe, otherwise could cause loss of funds.
> **Attention**: using delegatecall could incur risk, make sure the storage layout of state variables of current contract and target contract is same, and target contract is safe, otherwise could cause loss of funds.
## `delegatecall` use cases?
Currently there are 2 major use cases for delegatecall:
Expand All @@ -73,7 +73,7 @@ contract C {
}
}
```
### Call Initizalization Contract B
### Call Initialization Contract B
First, contract `B` must have the same state variable layout as target contract `C`, 2 variables and the order is `num` and `sender`.

```solidity
Expand Down
73 changes: 73 additions & 0 deletions Languages/en/52_EIP712_en/EIP712Storage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
// By 0xAA
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract EIP712Storage {
using ECDSA for bytes32;

bytes32 private constant EIP712DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
bytes32 private constant STORAGE_TYPEHASH = keccak256("Storage(address spender,uint256 number)");
bytes32 private DOMAIN_SEPARATOR;
uint256 number;
address owner;

constructor(){
DOMAIN_SEPARATOR = keccak256(abi.encode(
EIP712DOMAIN_TYPEHASH, // type hash
keccak256(bytes("EIP712Storage")), // name
keccak256(bytes("1")), // version
block.chainid, // chain id
address(this) // contract address
));
owner = msg.sender;
}

/**
* @dev Store value in variable
*/
function permitStore(uint256 _num, bytes memory _signature) public {
// Check the signature length, 65 is the length of standard r, s, v signatures
require(_signature.length == 65, "invalid signature length");
bytes32 r;
bytes32 s;
uint8 v;
// Currently, assembly (inline assembly) can only be used to obtain the values of r, s, and v from the signature.
assembly {
/*
The first 32 bytes store the length of the signature (dynamic array storage rules)
add(sig, 32) = pointer to sig + 32
Equivalent to skipping the first 32 bytes of signature
mload(p) loads the next 32 bytes of data starting from memory address p
*/
// 32 bytes after reading the length data
r := mload(add(_signature, 0x20))
//32 bytes after reading
s := mload(add(_signature, 0x40))
//Read the last byte
v := byte(0, mload(add(_signature, 0x60)))
}

// Get signed message hash
bytes32 digest = keccak256(abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(abi.encode(STORAGE_TYPEHASH, msg.sender, _num))
));

address signer = digest.recover(v, r, s); // Restore signer
require(signer == owner, "EIP712Storage: Invalid signature"); // Check signature

// Modify state variables
number = _num;
}

/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
115 changes: 115 additions & 0 deletions Languages/en/52_EIP712_en/eip712storage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EIP-712 Signature Example</title>
</head>
<body>
<h1>EIP-712 Signature Example</h1>

<label for="name">Name:</label>
<input id="name" value="EIP712Storage">
<br>
<label for="chainId">Chain ID:</label>
<input id="chainId" value="1">
<br>
<label for="contractAddress">Contract Address:</label>
<input id="contractAddress" value="0xf8e81D47203A594245E36C48e151709F0C19fBe8">
<br>
<label for="spender">Spender:</label>
<input id="spender" value="0x5B38Da6a701c568545dCfcB03FcB875f56beddC4">
<br>
<label for="number">number:</label>
<input id="number" value="100">
<br>
<button id="connectButton">Connect MetaMask</button>
<button id="signPermitButton" disabled>Sign Permit</button>
<br>
<pre id="signatureOutput"></pre>

<h5>Wallet address: <span class="showAccount"></span></h5>
<h5>ChainID: <span class="showChainID"></span></h5>
<h5>ETH Balance: <span class="showETHBalance"></span></h5>
<h5>Signature data: <span class="showSignature"></span></h5>

<script type = "module">
import { ethers } from "https://cdnjs.cloudflare.com/ajax/libs/ethers/6.3.0/ethers.js"; const ethereumButton = document.querySelector('.connect');
const showAccount = document.querySelector('.showAccount');
const showChainID = document.querySelector('.showChainID');
const showETHBalance = document.querySelector('.showETHBalance');
const showSignature = document.querySelector('.showSignature');
const connectButton = document.getElementById("connectButton");
const signPermitButton = document.getElementById("signPermitButton");

let provider;
let signer;

async function connectMetaMask() {
// Get provider
const provider = new ethers.BrowserProvider(window.ethereum)

//Read wallet address
const accounts = await provider.send("eth_requestAccounts", []);
const account = accounts[0]
console.log(`Wallet address: ${account}`)
showAccount.innerHTML = account;

//Read chainid
const { chainId } = await provider.getNetwork()
console.log(`chainid: ${chainId}`)
showChainID.innerHTML = chainId;

//Read ETH balance
const signer = await provider.getSigner()
const balance = await provider.getBalance(signer.getAddress());
console.log(`Ethereum balance: ${ethers.formatUnits(balance)}`)
showETHBalance.innerHTML = ethers.formatUnits(balance);
signPermitButton.disabled = false;
}

async function signPermit() {
const name = document.getElementById('name').value;
const version = "1";
const chainId = parseInt(document.getElementById('chainId').value);
const contractAddress = document.getElementById('contractAddress').value;
const spender = document.getElementById('spender').value;
const number = document.getElementById('number').value;
const provider = new ethers.BrowserProvider(window.ethereum)
const signer = await provider.getSigner()
const owner = await signer.getAddress();

const domain = {
name: name,
version: version,
chainId: chainId,
verifyingContract: contractAddress,
};

const types = {
Storage: [
{ name: "spender", type: "address" },
{ name: "number", type: "uint256" },
],
};

const message = {
spender: spender,
number: number,
};

try {
console.log(message)
const signature = await signer.signTypedData(domain, types, message);
console.log("Signature:", signature);
showSignature.innerHTML = `${signature}`;
} catch (error) {
console.error("Error signing permit:", error);
}
}

connectButton.addEventListener(`click`, connectMetaMask)
signPermitButton.addEventListener(`click`, signPermit)
</script>
</body>
</html>
Binary file added Languages/en/52_EIP712_en/img/52-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Languages/en/52_EIP712_en/img/52-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Languages/en/52_EIP712_en/img/52-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Languages/en/52_EIP712_en/img/52-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit e351480

Please sign in to comment.