Solidity - call, delegatecall, staticcall

김윤수·2023년 3월 30일

Solidity

목록 보기
3/3

call

일반적으로 다른 컨트랙트의 함수를 호출할 때 쓰던 방식.
유저가 컨트랙트 A에서 컨트랙트 B의 함수 호출시 컨트랙트 A가 msg.sender가 되어 B의 state를 변경시킨다.

delegatecall

유저가 컨트랙트 A에서 컨트랙트 B의 함수 호출시 유저가 msg.sender가 되어 A의 state를 변경시킨다.
컨트랙트 B의 함수만 가져다 쓴다고 보면 되겠다.

예제

Zombie.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

contract Zombie {
  string public name;
  uint public dna;

...

  function setDNA(
    address _contract,
    uint _dna
  ) public returns (bool, bytes memory) {
    (bool success, bytes memory data) = _contract.delegatecall(
      abi.encodeWithSignature("setVars(uint256)", _dna)
    );
    return (success, data);
  }
}

ZombieTemp.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

contract ZombieTemp {
  string public name;
  uint public dna;

  function setVars(uint _dna) public {
    dna = _dna;
  }
}

트러플 테스트 결과

ZombieTemp.sol의 dna는 별도로 지정해준 바가 없기에 기본값인 0으로 delegatecall 이후에도 바뀌지 않은 모습이다.

staticcall

EIP-214에 추가된 opcode.

To increase smart contract security, this proposal adds a new opcode that can be used to call another contract (or itself) while disallowing any modifications to the state during the call (and its subcalls, if present).

State를 변경하지 않는 점을 제외하면 다른 특성은 call과 동일하다.
특성상 상태 변수를 변경할 경우 호출하지 않는다.

function setDNAbyStaticcall(address _contract, uint _dna) public {
  (bool success, bytes memory data) = _contract.staticcall(
    abi.encodeWithSignature("setVars(uint256)", _dna)
  );
  emit Set(success);
}

상태 변수를 변경하는 함수를 staticcall을 통해 호출할 경우,

이렇게 false를 반환한다.

참고

https://medium.com/coinmonks/call-staticcall-and-delegatecall-1f0e1853340
https://eips.ethereum.org/EIPS/eip-214

0개의 댓글