proxy contract의 기본 구조

Delegatecall and Proxy Pattern
하지만 만약 transferFrom()을 호출하되, 해당 함수의 로직만 이용하고 관련 스토리지 변경은 CallERC20 컨트랙트에 적용하고 싶다면? 이를 가능하게 하는것이 바로 delegatecall 이다.
솔리디티는 다른 컨트랙트를 호출할 때, 크게 두가지 EVM opcode중 하나를 사용할 수 있도록 한다. 바로 call과 delegatecall 이다. call이 바로 우리가 통상적으로 컨트랙트를 호출할 때 사용하는 opcode이다. 바로 위의 CallERC20 예시 또한 내부적으로는 call opcode를 통해 transferFrom()을 호출한다.
이외에도 staticcall 이라는 친구가 있는데, 상태를 변경하지 않는 call 이라는 의미이다. 지금은 크게 중요하지 않으니 참고만 해두자.
delegatecall은 상당히 특이한 친구인데, 이 opcode는 다른 컨트랙트의 코드를 사용하되, 실행 환경(Context)은 기존 컨트랙트에서 수행될 수 있도록 한다. 아래 다이어그램을 살펴보자.

A 컨트랙트가 B 컨트랙트를 호출할 때, delegatecall을 이용하게 되면 B 컨트랙트의 Code를 사용하지만, Storage는 A 컨트랙트를 사용하게 된다. 트랜잭션 실행의 컨텍스트(Context)가 그대로 유지되는것이 delegatecall의 핵심이다.
delegatecall은 다른 컨트랙트 어카운트의 code를 사용하되, storage는 기존 컨트랙트 어카운트의 그것을 사용한다. 이렇게 delegatecall을 이용하게 되면 스토리지는 그대로 유지한채로 컨트랙트의 로직이 되는 부분을 상황에 맞게 사용할 수 있게 된다. 프록시 컨트랙트에 어떠한 로직 컨트랙트를 사용할 것인지 주소만 명시해두면 되는것이다.
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
// ...
}
let result 부분에서 사용되고 있다.
참고
https://medium.com/@aiden.p/업그레이더블-컨트랙트-씨-리즈-part-2-프록시-컨트랙트-해체-분석하기-95924cb969f0
'BlockChain > Solidity' 카테고리의 다른 글
[Solidity] Wolfgame은 왜 ERC-1155를 사용하지 않았을까? (1) | 2023.03.12 |
---|---|
[blockchain] view 함수는 정말 가스비가 무료일까? (view function cost?) (0) | 2023.03.12 |
[Solidity] CA, EOA (0) | 2022.08.04 |
[Solidity] 임의의 이름으로 토큰 만들기 (0) | 2022.07.27 |
[Solidity] event란? 쓰는 이유는? (0) | 2022.07.27 |
댓글