대전대학교 대학원 | 블록체인 기술 특론 | 연삼흠 교수 | WIA-FIN-007
mapping은 모든 키에 대해 기본값을 반환하므로, 존재 여부를 직접 확인할 수 없습니다. 해결 방법:
bool exists 필드를 추가하여 플래그로 관리mapping(key => bool)을 유지mapping은 해시 기반 자료구조로, 어떤 키가 설정되었는지 추적하지 않습니다. 모든 가능한 키에 대해 기본값이 존재하는 것으로 간주합니다. 순회가 필요하면 별도의 배열에 키를 저장해야 합니다:
address[] public keys;
OpenZeppelin의 EnumerableMap 라이브러리를 사용하면 순회 가능한 mapping을 구현할 수 있습니다.
struct를 mapping에 저장하면 storage에 저장됩니다. 주의점:
mapping(a => mapping(b => c)))은 가능하지만 가스비 주의용도에 따라 다릅니다:
대부분의 DApp에서는 mapping + 배열 조합이 가장 실용적입니다.
매우 중요합니다. _;는 원래 함수의 본문이 삽입되는 위치입니다.
_; 앞의 코드: 함수 실행 전에 실행 (전처리)_; 뒤의 코드: 함수 실행 후에 실행 (후처리)예를 들어, 재진입 공격(Reentrancy) 방지를 위한 mutex modifier에서는 _;의 위치가 보안에 직접적인 영향을 줍니다.
외부 계약을 호출할 때, 호출된 계약이 원래 계약의 함수를 다시 호출하여 상태가 업데이트되기 전에 자금을 반복 인출하는 공격입니다. 2016년 The DAO 해킹(약 6천만 달러 피해)의 원인이었습니다.
방지법:
ReentrancyGuard 사용OpenZeppelin은 검증된 스마트 계약 라이브러리를 제공하는 오픈소스 프로젝트입니다. ERC-20, ERC-721, AccessControl, ReentrancyGuard 등 표준 구현을 제공합니다. 실무에서는 직접 구현보다 OpenZeppelin 라이브러리를 사용하는 것이 안전합니다. 수많은 감사(audit)를 거쳤기 때문입니다.
계약의 상태 머신을 구현할 때 사용합니다. 투표 계약의 Created/Voting/Ended처럼, 계약이 특정 생애주기를 가질 때 유용합니다. enum은 내부적으로 uint8로 저장되며, 유효하지 않은 값은 자동으로 거부됩니다. WIA-FIN-007에서는 금융 계약의 상태 관리에 enum 사용을 권장합니다.
둘 다 변경 불가능한 변수를 선언하지만 차이가 있습니다:
uint256 constant MAX = 100;address immutable owner;둘 다 storage 슬롯을 사용하지 않으므로 가스비가 크게 절감됩니다. constant는 바이트코드에 직접 포함되고, immutable은 배포 시 바이트코드에 기록됩니다.
EVM의 storage 슬롯은 32바이트(256비트)입니다. 작은 타입의 변수를 연속으로 선언하면 하나의 슬롯에 함께 저장됩니다:
uint128 a; uint128 b; -> 1슬롯 (32바이트)uint256 a; uint128 b; -> 2슬롯struct 내에서도 작은 타입을 인접하게 배치하면 가스를 절약할 수 있습니다. 선언 순서가 중요합니다.
사용할 수 있지만 주의가 필요합니다. 반복 횟수가 많으면 블록 가스 한도를 초과하여 트랜잭션이 영원히 실행 불가능해질 수 있습니다. 이를 "DoS(Denial of Service) 취약점"이라고 합니다.
권장 사항:
Solidity 0.8.4부터 도입된 커스텀 에러는 문자열 에러 메시지보다 적은 바이트코드를 생성합니다:
error Unauthorized(); (4바이트) vs require(false, "Only admin can call") (문자열 전체 저장)
특히 에러 메시지가 긴 경우 가스 절감 효과가 큽니다. 대규모 계약에서는 모든 require를 커스텀 에러로 교체하는 것이 좋습니다.
아닙니다. 이벤트는 트랜잭션 로그(receipt)에만 저장되며, 계약 코드 내에서는 접근할 수 없습니다. 오직 외부 애플리케이션(Web3.js, ethers.js, The Graph 등)에서만 읽을 수 있습니다. 계약 내에서 읽어야 하는 데이터는 반드시 상태 변수(storage)에 저장해야 합니다.
하나의 이벤트에서 indexed 매개변수는 최대 3개입니다. indexed 매개변수는 토픽(topic)으로 저장되어 효율적인 필터링이 가능합니다. indexed가 아닌 매개변수는 데이터 부분에 저장되며, 필터링은 불가능하지만 더 많은 데이터를 저장할 수 있습니다.
주로 두 가지 라이브러리를 사용합니다:
필요한 것은 (1) 계약의 ABI (2) 배포된 계약 주소 (3) Provider(MetaMask 등)입니다. ABI는 계약의 인터페이스를 정의하는 JSON으로, Remix에서 컴파일 후 복사할 수 있습니다.
블록체인은 투명하므로 기본적으로 비밀 투표가 어렵습니다. 구현 방법:
Commit-Reveal이 가장 실용적이며, 심화 과제로 구현해볼 수 있습니다.