개발하기좋은날

스마트 컨트랙트 시큐리티 패턴 본문

BlockChain

스마트 컨트랙트 시큐리티 패턴

devbi 2022. 11. 2. 18:16
반응형

이전 포스팅에서 

Checks Effects Interaction, Mutex Pattern

알아보고 재진입 공격에 대해서 포스팅을 하였습니다

 

이번엔 그밖에 다양한 시큐리티 패턴에 대해 알아보고자 합니다 

 

1. Emergency Stop Pattern

- 블록체인에 배포된 스마트컨트랙트는 수정이 불가능합니다 

그래서 예기치 못한 버그로 인해서 큰 피해를 줄 수 있는데 Emergency Stop Pattern은 특정 함수들이 실행되지 않도록 제어할 수 있도록 프로그래밍하는 패턴입니다. 쉽습니다 

contract EmergencyStop is Owned { 
  bool public contractStopped = false; 
  modifier haltInEmergency { 
    require(contractStopped) 
    _; 
  } 
  modifier enableInEmergency { 
    require(!contractStopped) 
    _; 
  } 
  function toggleContractStopped() public onlyOwner { 
    contractStopped = !contractStopped; 
  } 
  function deposit() public payable haltInEmergency { 
    // some code 
  }
  function withdraw() public view enableInEmergency { 
    // some code 
  } 
}

컨트랙트의 Owner만이 function의 제어권을 조절할수있습니다.

haltInEmergency로 함수를 제어합니다 Owner만이 contractStopped의 변수값을 수정할 수 있습니다.

 

2. Speed Bump Pattern

- 과속 방지턱 패턴은 이름에서 알 수 있듯이 보행자를 보호하기 위한 안전장치입니다 

Speed Bump Pattern은 특정 함수를 실행하기 위해서 의도적으로 시간을 지연시키거나 한 번에 인출할 수 있는 

금액에 제한을 두는 패턴입니다.

이렇게 하는 이유는 특정 함수를 다수의 사용자가 무제한적으로 호출함으로 컨트랙트에 이상이 생기는 것을 방지하기 위함입니다.

contract SpeedBump { 
  struct Withdrawal { 
    uint amount; 
    uint requestedAt; 
  } 
  mapping (address => uint) private balances; 
  mapping (address => Withdrawal) private withdrawals; 
  uint constant WAIT_PERIOD = 7 days; 
  function deposit() public payable { 
    if(!(withdrawals[msg.sender].amount > 0)) {
      balances[msg.sender] += msg.value; 
    }
  } 
  function requestWithdrawal() public { 
    if (balances[msg.sender] > 0) { 
      uint amountToWithdraw = balances[msg.sender]; 
      balances[msg.sender] = 0; 
      withdrawals[msg.sender] = Withdrawal({ amount: amountToWithdraw, requestedAt: now }); 
    } 
  }
  function withdraw() public {
    if(withdrawals[msg.sender].amount > 0 && now > withdrawals[msg.sender].requestedAt + WAIT_PERIOD) { 
      uint amount = withdrawals[msg.sender].amount; 
      withdrawals[msg.sender].amount = 0; 
      msg.sender.transfer(amount); 
     } 
  } 
}

deposit을 통해 입금한 Balances를 인출하기 위해서는 withdraw() 수행이 가능합니다 

인출하기위해서는 두 가지 조건이 필요합니다

requestWithdrawal() 호출을 통해서 예약을 하고, WAIT_PERIOD의 인출시간이 지나야지만 최종적으로 인출이 가능합니다. 

 

 

3. Rate Limit Pattern 

- 위 패턴은 함수를 호출할 수 있는 빈도를 제한하는 패턴입니다. 

아래의 코드는 함수 F가 한번 실행이 되면 1분이 지나야 만 다시 실행할 수 있도록 구현되어 있습니다. 

contract RateLimit { 
  uint enabledAt = now; 
  modifier enabledEvery(uint t) { 
    if (now >= enabledAt) { 
      enabledAt = now + t; 
      _; 
    } 
  } 
  function f() public enabledEvery(1 minutes) { 
    // some code 
  } 
}

 

4. Balance Limit Pattern

- 스마트 컨트랙트 내의 잔액의 최댓값을 설정하여, 최대값 이상으로 컨트랙트로 금액이 보내지는 것을 막는 패턴입니다.

contract LimitBalance { 
  uint256 public limit; 
  function LimitBalance(uint256 value) public { 
    limit = value; 
  } 
  modifier limitedPayable() { 
    require(this.balance <= limit); 
    _; 
  } 
  function deposit() public payable limitedPayable { 
    // some code 
  } 
}

위 코드는 LimitBalance 함수를 통해 컨트랙트에서 보유할 수 있는 최대 잔액을 설정한 후, 보유한 잔액이 설정된 최대 잔액보다 작을 때만 deposit 함수를 실행할 수 있도록 구현되어 있습니다.

 

위와 같은 패턴들은 예기치 못하는 상황을 사전에 방지할 수 있으며 스마트 컨트랙트의  안정성을 높여주는 패턴이므로 

꼭 염두에 두자

다음엔 Maintenance Pattern에 대해서 알아보자

 

 

 

  

반응형

'BlockChain' 카테고리의 다른 글

이더리움의 MEV (Maximal Extractable Value)  (0) 2022.12.07
Fallback, Receive 그리고 재진입 공격  (0) 2022.10.30
재진입 공격 방지 (Re-Entrancy)  (0) 2022.10.28
External Call 보안  (0) 2022.10.28
채굴 (Mining)  (0) 2022.10.17
Comments