부족한 가스 그리핑 공격은 sub-call을 수행할 때 발생할 수 있다. 예를 들어 Acontract가 Bcontract의 어떤 함수를 실행할 때 공격자는 Acontract에 대한 충분하지 않은 가스를 제공한다. 그랬을 경우에 1. 트랜잭션의 실패 2. Acontract에서 실패했지만 계속해서 실행할 수 있다. 그것으로 특정한 컨트랙트에 대해서 계속해서 방해를 할 수 있다. 그러니까 공격자에게 '직접적'인 이득은 없지만 프로토콜의 시스템을 방해하는 것이다.
우선 griefing attack은 가스문제 전에 악의적인 접근을 지속하는 것을 말한다.
예시 컨트랙트로 설명하겠다.
contract DelayedWithdrawal {
address beneficiary;
uint256 delay;
uint256 lastDeposit;
constructor(uint256 _delay) {
beneficiary = msg.sender;
lastDeposit = block.timestamp;
delay = _delay;
}
modifier checkDelay() {
require(block.timestamp >= lastDeposit + delay, "Keep waiting");
_;
}
function deposit() public payable {
require(msg.value != 0);
lastDeposit = block.timestamp;
}
function withdraw() public checkDelay {
(bool success, ) = beneficiary.call{value: address(this).balance}("");
require(success, "Transfer failed");
}
}
여기서 보면 문제가 없어보이지만 누구든 deposit함수를 실행할 수 있기 때문에 griefing attacker는 최소한의 value ( = 1 wei)를 넣고 계속해서 컨트랙트를 실행하면 lastDeposit이 계속해서 최신 block.timestamp로 변경되기 때문에 누구도 withdraw를 하지 못하는 경우가 생긴다.
이어서 Insufficient Gas Griefing은 주로 외부 호출을 실행하는 컨트랙트에 영향을 미치는 공격이다. 이 공격에서 공격자는 최상위 함수의 성공을 보장하기 위해 충분한 가스를 제공하는 동시에 가스 소진으로 인해 외부 호출의 실패를 야기시킬 수 있다. 그러니까 최상위 함수는 실행하지만 스테이트의 변경은 발생하지 않는다.
contract Relayer {
mapping (bytes => bool) executed;
address target;
function forward(bytes memory _data) public {
require(!executed[_data], "Replay protection");
// more code for signature validation in between
executed[_data] = true;
target.call(abi.encodeWithSignature("execute(bytes)", _data));
}
}
위 컨트랙트에서 forward함수를 실행하면 target.call함수의 실행결과를 리턴하지 않기 때문에 자연스럽게 실행될 것이다. 그래서 한번 체크가 된 _data에 대해서 execute함수가 실행되지 않았지만 다른 사람이 동일한 _data로 forward함수를 실행하면 실패할 것이다.
insufficient gas gridfing을 막는 두가지 방법이 있다.
1. relay tx에 허가된 유저만 가능하게 한다.
2. 충분한 가스를 제공하도록 요구한다.
2번 가스 체크 방법
contract GasCalc {
uint public gasUsed;
uint64[] public numArr;
function updateArr(uint64 _num) external returns(uint, uint){
uint initGas = gasleft();
numArr.push(_num);
uint finalGas = gasleft();
gasUsed = initGas - finalGas;
return (initGas , finalGas);
}
}
사용한 가스 : 44422
[ 참고 및 추가자료 ]
https://swcregistry.io/docs/SWC-126/
https://scsfg.io/hackers/griefing/
https://www.rareskills.io/post/solidity-gasleft