Call과 DelegateCall에 대해서 좀 더 자세히 알아 봅니다.
Call vs DelegateCall
Call
Call은 Context가 Call의 대상이 되는 Contract로 변경됩니다.
무슨 말이냐하면, User가 Contract A를 호출하고, Contract A가 Contract B를 호출 하면, Contract A에서는 msg.sender이 User가 되지만, Contract B에서는 msg.sender이 Contract A가 된다는 말입니다.
그 말은 Contract B의 어떤 함수가 실행되고 Storage가 변경되는 부분이 있는 경우 Contract B 내부에 선언된 Storage 변수의 값이 변경됩니다.
Delegate Call
반면에 DelegateCall을 사용하면 Contract B의 함수가 실행되는 중에도 Context가 그대로 Contract A에 남아 있다는 말이 됩니다.
Contract B의 어떤 함수가 호출 되더라도 Contract A에 있는 Storage가 값이 변경됩니다.
msg.sender도 그대로 User로 남아 있게 되구요.
그렇기 때문에 반드시 Storage가 Contract A에서도 변경될 수 있어야 함으로 Contract A와 B의 Storage "형태"와 "순서"가 반드시 동일해야 작동을 합니다.(변수명은 달라도 되지만 "순서"!!!와 "형태"!!!가 중요)
Storage Layout
- 각각 컨트랙트 변수 들은 32바이트 단위로 나뉘어 각각의 슬롯에 저장됩니다. 이것을 Storage Layout이라고 말합니다.
- 위의 이미지의 Test 컨트랙트를 보면,
uint256 test = 0;
은 슬롯 0에 저장 uint256 A;
는 슬롯 1에 저장...- 아래 컨트랙트에서 Storage 변수명은 다르더라도 변경되는 Storage의 순서에 따라 DelegateCall을 요청한 컨트랙트의 Storage 값이 변경됩니다.