[SCH] Flash Loan Attack

frenchkebab·2023년 5월 13일
0

sch

목록 보기
2/3

Flash Loan Attack1

token.safeTransfer(borrower, amount);
target.functionCall(data);

다음과 같이 토큰을 전송하고 callback 함수를 부른다.

뭐가 문제일까?

공격 시나리오

  1. flash loan pool 컨트랙트에다가 대출금을 보낸다
    (그럼 pool의 balance가 변하지 않음)
  2. target을 대출할 token contract로 설정해놓고,
bytes memory data = abi.encodeWithSignature("approve(address,uint256)", address(this), amount);

얘를 보내게 하면?

flash loan 돈은 하나도 안빠져나갔으므로, 상환에 대한 require문을 통과한 뒤 트랜잭션이 완료되고 나서,
transferFrom으로 돈을 빼나가면 된다.

Prevention

1. Sanity Check

require(to != address(this))

무조건 Flash Loan이 일어나면 대출 컨트랙트에서 자금이 나갔다 들어오게끔 하면 된다.

2. receiver 함수 interface 지정

AAVEFlash LoanUniswap V2Flash Swap 모두 receiver 함수에 대한 interface를 지정해 두었다.

처음에는 그냥 편의를 위한 것이라고 생각하였으나,,,

이러한 공격에 대한 Prevention이다.

Flash Loan Attack2

function depositETH() external payable {
    balances[msg.sender] += msg.value;
}

function flashLoanETH(uint256 amount) external {
  uint256 balanceBefore = address(this).balance;
  require(balanceBefore >= amount, "Requested amount is greater than Vault balance");
  IFlashLoanEtherReceiver(msg.sender).callBack{value: amount}();
  require(address(this).balance >= balanceBefore, "Need to pay back the loan");
}

공격 시나리오

Flash Loan을 받자마자 callbackdeposit을 넣어주면 무한으로 balance mapping을 펌핑시킬 수 있다.
(정당하게 withdraw가 가능해짐)

deposit함수는 mapping을 쓰는데,

require(address(this).balance >= balanceBefore, "Need to pay back the loan");

flash loan에 대한 상환의 체크는 mapping을 사용하지 않기 때문이다.

Prevention

아이디어1

reentrancy gaurd처럼 lock variable을 걸어서,
flashLoan 함수 실행 중에는 deposit 함수 자체를 호출할 수 없도록 할 수 있을 것 같다.

아이디어2

balances mapping 값이 flash loan 전후로 바뀌지 않았는지를 체크 (deposit이 불가하도록)할 수 있다.

지금 상황에서는 사실상 deposit 함수 호출을 불가하게끔 하는 것이 최선인 것 같다.

profile
Blockchain Dev Journey

0개의 댓글