UniswapV2ERC20.sol
pragma solidity =0.5.16;
import './interfaces/IUniswapV2ERC20.sol';
import './libraries/SafeMath.sol';
//유니스왑은 인터페이스를 자체 제작하여 ERC-20 인터페이스를 끌고오고있으며
// safemath 를 사용하여 언더플로우 오버플로우를 예방하고 있다
contract UniswapV2ERC20 is IUniswapV2ERC20 {
using SafeMath for uint;
// uint 자료형 오버플로우 방지
string public constant name = 'Uniswap V2';
string public constant symbol = 'UNI-V2';
uint8 public constant decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
//주소와 총 잔액을 매핑하여 balanceOf 확인
mapping(address => mapping(address => uint)) public allowance;
// allowance는 입력한 두 개의 주소 값에 대한 _allowance 값 다시말해 owner가 spender에게 토큰을 등록한 양을 반환하는 함수이고
//여기서는 매핑 과정이다.
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public nonces;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
constructor() public {
uint chainId;
//이더리움 네트워크 체인이 여러가지 존재하기에
assembly {
chainId := chainid
}
// assembly를 이용해 가스 비 절약, := 연산자로 초기화
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainId,
address(this)
)
);
}
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
//토큰발행함수
//민트 함수는 받을 사람의 주소와, 받을 토큰의 양을 받는다
//총 공급량에 받을 토큰의 양을 더해주고
//모든 잔액을 가진 배열이 balanceof 인데 받을 주소에 추가 공급량을 추가해준다
// emit => event에 기록하는 용도
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
//토큰소각함수
//소각하는 주소와, 토큰의 양을 함수가 받고
//민트 함수와 반대의 개념으로 이해하면 된다.
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
//spender 에게 value 만큼의 토큰을 인출할 권리를 부여.
//이 함수를 이용할 때는 반드시 Approval 이벤트 함수를 호출해야 한다.
//approve 는 spender 가 당신의 계정으로부터 amount 한도 하에서 여러 번 출금하는 것을 허용.
//이 함수를 여러번 호출하면, 단순히 허용량을 amount 으로 재설정한다
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
// 전송함수
// 호출이 정상적으로 완료 되었을 경우 Transfer event 발생
//실행한 사람(sender)이 가진 토큰의 지갑에서 토큰을 개수만큼 빼고,
//받을 사람(recipient)의 토큰 지갑에 개수만큼 더해준다
function transferFrom(address from, address to, uint value) external returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
// uint256(-1)는 uint256의 max 값
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
//transferFrom은 양도를 수행하는 거래 대행자(msg.sender)가
//from이 허락해준 값만큼 상대방(to)에게 토큰을 이동
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
//require 문으로 한번 걸러주는데
//deadline을 블록타임스탬프로 체크한다. 블록타임 스탬프 시간이 데드라인을 초과 할 경우 UniswapV2: EXPIRED 출력된다.
//UniswapV2: EXPIRED 는 메인넷 브로드캐스트 하는데 걸리는 시간이 오래걸리게 되면 나오는 결과
bytes32 digest = keccak256(
abi.encodePacked(
//encode 방식 보다 간편하게 인코딩 하기위해 abi.encodePaced 함수를 사용
//인수의 압축 인코딩 수행
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
// 서명에서 주소를 복구하는 ecrecover 함수 사용
// 서명 값인 v, r, s 값과 데이터 hash값을 ecrecover에 넣고 실행하면 데이터를 서명한 사용자의 주소 출력
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
_approve(owner, spender, value);
}
}
'DeFi 뿌수기' 카테고리의 다른 글
유니스왑 v2 백서 분석 (0) | 2023.02.28 |
---|---|
유니스왑 V2 해체하기 Factory Contract (0) | 2022.04.14 |
DeFi - UniSwap 리서치 (0) | 2022.04.11 |
댓글