State Trie
Storage Trie
Transactions Trie
Receipts Trie
*상태가 들어가는 트라이
ex)
이더잔고 알고 싶으면 지갑주소 넣고 World state trie로 이동
erc20잔고 알고 싶으면 account storage contents trie로 이동
await web3.eth.
일반 지갑에는 storage가 존재하지 않음
storageRoot, codeHash는 CA만 존재
balance는 이더잔고
nonce는 value
a를 보려거든 위 사진과 같은 플로우
From이 나고 To가 ERC-20. 내가 mint token의 method ID를 가지고 ERC-20을 호출 -> 내가 스마트컨트랙트를 호출한다(아래 사진)
ERC-20 12번째 줄
mapping(address account => uint256) private _balances;
: "얘는 이만큼 잔고를 갖고 있어"
: 이더잔고의 정보는 컨트랙트와 연결되어 있음
: 이더잔고의 통제권은 개인키에 있음
: 결국 ERC-20의 통제권은 내가 아닌 컨트랙트, 컨트랙트 만든 인간에게 있음
transfer from은 내 돈을 남이 쓰는 듯한 느낌이 있는데 그게 왜 그런지? 왜 가능한지?
: _balance가 존재하기에 사실상 통제권이 나에게 없다.
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
-> utils 밑에 있는 건 다양한 곳에 사용. msgSender, wei단위에서 이더로 바꾸기, sha3 etc
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
->
ex) $1000 중에서 $70만큼 자동으로 매수가 되도록 걸어놓는 것.
거래를 일으키는 주체는 내가 아니라 부탁을 한 스마트컨트랙트가 자동으로 하는 것. 스마트컨트랙트에게 $70만큼 거래할 수 있도록 위임한 것.
다른 아이에게 erc-20 관련된 것을 위임할 수 있으면 구현할 수 있는 범위가 매우 넓어짐.
mapping(address account => mapping(address spender => uint256)) private _allowances;
->account : 내가, spender 얘한테, uint 얼마를 위임해줌
->52 allowance로 이동
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return 18;
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupply; -> 전체 발행량
}
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
} -> _balances로 가서 address 탄 다음 uint 나옴
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
-> address to 얘한테 uint value 보내줘
owner - 나는 to - 남한테 value -이만큼 보낸답니다
-> 69번줄 _transfer로 감
56. function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
} -> approve 해서 119번줄로 이동
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
} 주는 사람 0주소면 뭐가 잘못됐어 -> 에러
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
} 받는 사람 0주소면 뭐가 잘못된 거야 -> 에러
_update(from, to, value); -> 다른 함수로 호출, 바로 아래 79 update로 감
}
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from]; -> 너 지금 잔고 얼마야?
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
_totalSupply -= value;
}
} else {
unchecked {
_balances[to] += value;
}
}
emit Transfer(from, to, value); -> transfer라는 이벤트를 일어났고 emit , transfer는 ierc-20에 있음
}
민트랑 번은 토큰을 찍어내고 발행하는 것 -> 실질적 발행량이 변화를 일으킴
거래를 할 때는 from과 to 그리고 얼마가 가는지 나타내는 value가 있음
민트랑 번은 결국 받는 사람과 주는 사람의 잔고에 영향을 주는 것
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
} -> mint는 하늘에서 뚝 떨어지는 것
-> _update(0주소가, 나한테, value를 준다)
-> 79번 _update로 가서 첫 if에 걸리니 total supply 늘어남, 쭉 내려가서 unchecked _balance로 넘어가 value 늘어남
-> event emit
* from과 to에 고래 주소를 걸어놓는 경우가 많음
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
} -> burn은 있는 돈을 태워버리는 것, 땅바닥의 돈이 사라지는 경우.
-> 보내는 사람이 0주소인지 아닌지 확인하는 것
79 _update로 이동
-> burn은 토큰을 갖고 있는 애가 확인하는 것. 보내는 사람이 0주소인 건 말이 안 됨. burn 시키니까 내 지갑 잔고는 줄어들 것!
-> 받는 사람 주소는 0주소니까 total supply 줄 것
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
-> 허락해주는 과정. Approve 새로해준 상황.
승인해준 것을 갖다쓰는 것. 위의 119 approval-> 100(current)-30(value), false니까 emit이 발생하지 않음. 허락해준 양만 갈아끼우는 것