일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 배팅
- 싱글톤패턴
- RBAC
- 코드리뷰
- 프록시패턴
- 업그레이더블 컨트랙트
- solidity
- 재진입
- github
- 블록체인
- 인센티브 기반 커뮤니티
- 부트캠프
- 옵저버패턴
- 웹툰
- 멀티시그
- 디자인 패턴
- 솔리디티
- git add
- 회로차단
- 팩토리패턴
- github 에러
- 코드스테이츠
- 스테이트머신패턴
- 토큰노믹스
- 투표
- git commit
- 일시정지
- 트러블슈팅
- 팀 프로젝트
- Today
- Total
보다 더 생생한 기록
[Solidity] 면접 복기 [transfer/send/call, receive/fallback, Call/staticCall/delegateCall] 본문
[Solidity] 면접 복기 [transfer/send/call, receive/fallback, Call/staticCall/delegateCall]
viviviviviid 2024. 4. 27. 18:04여러가지 기본적인 부분들을 포함해 놓친부분이 너무 많았다.
1년전에 공부했던 부분과, 새로운 업데이트 사항을 적용시켜 녹여보자.
1. transfer / send / call
- transfer (2300 gas, 에러 발생)
- send (2300 gas, 성공여부 true / false)
- call (gas값 지정 가능, 성공여부 true / false) -> 재진입 공격 위험성 막기위해 19년 12월 이후 call 사용
2300 gas로 정해진 transfer과 send를 사용시, 밑의 receive 또는 fallback이 들어있는 컨트랙트로 자금을 보내도 실패할 가능성이 높음. receive 또는 fallback이 이더가 들어옴을 감지하고 이벤트 로그를 발생시켜야하는데, 그 이벤트 발생까지 들어가는 가스비용이 2300보다 높을 가능성이 농후함.
즉 그래서 call을 쓰는것을 추천하는것 (게다가 0.8 버전 이후의 가스비 상승때문도 있음)
2. receive / fallback / delegateCall
fallback(대비책 함수) : 함수를 실행하면서 이더를 보낼때, 불려진 함수가 없을 때 작동
특징
- 이름이 없는 무기명 함수
- external 필수
- payable
왜 쓰는가
- CA가 이더를 받을 수 있도록
- 이더 받고 난 후 어떠한 행동을 취하게 할 수 있다.
- call 함수로 없는 함수가 불려질때, 어떠한 행동을 취하게 할 수 있다.
fallback() external payable {
emit JustFallback(msg.sender, "JustFallback is called");
}
그 뒤 이렇게 call을 해보면 call 함수로 존재하지 않는 함수가 불려졌으므로
(bool success,) = _to.call{value:msg.value}{"HI"} // 존재하지 않는 함수 "HI"를 call
JustFallback 이벤트가 발생한다.
receive : 순수하게 이더만 받을때 작동
이 함수를 통해서 컨트랙트가 이더를 받음.
1. 외부에서 이더가 보내지니까 : external
2. 이더 전송관련이니까 : payable
receive() external payable {
emit ReceiveFallback(msg.sender, msg.value, "ReceiveFallback is called");
}
3. Call / Static Call / Delegate Call
Call
일반적으로 다른 컨트랙트의 함수를 호출할때 쓰는 방식
컨트랙트 A에서 컨트랙트 B의 함수 호출 시, 컨트랙트 A가 msg.sender가 되어 B의 state를 변경시킨다.
Delegate Call
유저가 컨트랙트 A에서 컨트랙트 B의 함수 호출 시, 유저가 msg.sender가 되어 A의 state를 변경시킨다.
중요한 차이점
- Call과는 다르게, state가 변경되는 과정이 컨트랙트 A에서 발생함을 알 수 있다.
- Call과는 다르게, msg.sender 또한 호출자로 유지된다.
즉, 컨트랙트 B의 코드의 함수 내용만 바꾸면, 언제든지 컨트랙트 A에 새로운 알고리즘을 적용할 수 있다. (컨트랙트의 불변성 파훼)
예제
StorageManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
contract StorageManager {
uint public value;
function updateValue(address _logicContract, uint _newValue) public returns (bool success) {
(success,) = _logicContract.delegatecall(
abi.encodeWithSignature("setValue(uint256)", _newValue)
);
return success;
}
}
DataLogic.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
contract DataLogic {
uint public value;
function setValue(uint _value) public {
value = _value;
}
}
예제 코드 설명
- StorageManager는 state가 변경 될 컨트랙트 A, DataLogic은 로직을 처리하는 컨트랙트 B
- StorageManager 컨트랙트의 updateValue 함수는 DataLogic 컨트랙트의 setValue 함수를 delegatecall로 호출하여 StorageManager의 value 상태 변수를 업데이트
- delegatecall은 호출된 함수(setValue)가 StorageManager의 저장 공간을 사용하도록 하여, StorageManager의 상태가 변경. 이 때 msg.sender는 StorageManager를 호출한 원래의 호출자가 됨
직접 돌려보는게 이해하기에 편함
Static Call
Call과 거의 비슷하지만 state를 변경하지 않는다는점만 다름.
: 스마트컨트랙트에서 상태를 변경하지 않고 데이터를 읽기 위한 호출 방법.
StaticCall은 함수가 상태를 변경하지 않음을 보장하며, 주로 pure와 view 함수에 이용. 만약 staticCall이 상태변경을 시도하는 함수를 호출하면 트랜잭션이 실패됨
'블록체인' 카테고리의 다른 글
[Solidity] 업그레이더블 컨트랙트(Upgradable Contract) (0) | 2024.06.16 |
---|---|
[Solidity] 하드햇 튜토리얼 요약 (0) | 2024.06.11 |
[블록체인][리서치] 실제 사례를 보며 ERC-404를 이해해보자 (0) | 2024.04.10 |
[Dapp] NFT 담보 대출 플랫폼 설계 (0) | 2024.01.06 |
[블록체인] did 관련 문서, 레포, 레퍼런스 (0) | 2023.08.15 |