4. LendingPool 컨트랙트는 A컨트랙트의 executeOperation 함수를 호출합니다. executeOperation 는 IFlashLoanReceiver 에 정의되어있으며 플래시론을 활용할 컨트랙트는 이 인터페이스를 반드시 구현해야합니다. 각 파라미터에대한 설명은 여기를 참고해주세요.
즉 A컨트랙트가 실제로 자산을 빌려 동작을 수행하는 코드는 executeOperation 함수 내에서 수행되게 됩니다. executeOperation 함수는 내부에서 자산을 활용한 뒤 반드시 상환해야할 양(amounts + premium) 만큼의 자산(토큰) 을 보유하고 있어야 합니다. 또한 LendingPool 컨트랙트가 회수해 갈 수 있도록 상환해야할 양 이상 토큰을 LendingPool 컨트랙트에 approve 해주어야 합니다.
5. LendingPool 컨트랙트 는 마지막으로 amounts + premium 만큼의 토큰을 A컨트랙트 로부터 회수(transferFrom) 해옵니다.
위의 1~5 까지의 동작중에 예외가 발생하거나 특히
4. 에서 A컨트랙트 가 false를 리턴하는경우
5. 에서 LendingPool 컨트랙트가 자산이 회수가 불가능한 경우
모든 실행이 취소됩니다.
따라서 대출자(Borrower)는 담보 없이 자산을 빌릴 수 있고, 대여자(Depositor)는 위험성 없이 수수료를 얻을 수 있습니다.
지금까지의 과정을 도식으로 보면 아래와 같습니다.
플래시론 흐름도
파라미터 설명(flashLoan)
아래는 flashLoan 함수를 호출하기위한 파라미터와 이에대한 설명입니다.
address receiverAddress : 플래시론을 통해 대출을 발생시켰을 때 자산을 받아가고, executeOperation 가 구현되어있는 주소입니다. 이 예제에서는 A컨트랙트가 receiverAddress가 됩니다.
address[] calldata assets : 대출 받을 자산의 목록입니다.
uint256[] calldata amounts : 대출 받을 자산의 양 목록입니다.
uint256[] calldata modes : 대출 받을 자산들에 대해 대출 모드를 설정합니다. 현재 클레이뱅크의 대출모드는 0만 지원하며 나머지 타입은 추후 지원 예정입니다. 모드는 다음과 같습니다.
0 : 즉시 상환을 의미합니다. 플래시론을 통해 빌린 자산은 트랜잭션 종료와 함께 반드시 상환되어야 합니다. 그렇지 않은경우 실패합니다.
address onBehalfOf : 대출모드가 0이아닐때 사용됩니다. 현재는 값이 무시되므로 msg.sender 를 입력하셔도 무방합니다.
bytes calldata params : LendingPool 컨트랙트가 executeOperation 을 통해 사용자 A컨트랙트를 호출할때 넘겨줄 파라미터를 지정할 수 있습니다.
uint16 referralCode : 특정상황에 레퍼럴 구분자로 이용하기 위한 파라미터입니다. 일반 사용시에는 0을 입력하면 됩니다.
파라미터 설명(IFlashLoanReceiver)
아래는 executeOperation 함수를 호출하기위한 파라미터와 이에대한 설명입니다.
address[] calldata assets : 대출한 자산 목록을 의미합니다.
uint256[] calldata amounts : 대출한 금액 목록을 의미합니다.
uint256[] calldata premiums : 대출한 자산에 대한 수수료가 반영된 금액 목록을 의미합니다. 즉 amount + premium 만큼을 상환해야합니다.
address initiator : 플래시론을 호출한 주소를 나타냅니다.
bytes calldata params : 플래시론을 호출할때 넘겨준 파라미터 데이터를 나타냅니다
예시 컨트랙트
아래는 지금까지 설명했던 A컨트랙트의 예시입니다.
더 알아보기
플래시론을 활용할때 클레이뱅크 LedingPool 컨트랙트 의 flashLoan 함수를 호출하고 executeOperation 를 구현하는 것들이 모두 하나의 컨트랙트 (예시에서는 A컨트랙트) 일 필요는 없습니다.
필요에 따라서 일반 계정(EOA)에서 flashLoan 를 호출하고 receiverAddress 에 executeOperation 를 구현한 컨트랙트 주소(예시에서는 A컨트랙트)를 기입해도 무방합니다. 또한 또다른 컨트랙트인 B컨트랙트에서 호출할수도 있습니다. 각각 모두 msg.sender가 달라짐을 유의합니다.
위와같이 누구나 flashLoan 을 호출하여 다른 컨트렉트의 executeOperation 을 호출할 수 있으므로 griefing공격을 조심해야합니다. 해당 공격은 다음과 같이 이루어질 수 있습니다.
A컨트랙트에 자산(토큰)을 가지고있고 플래시론을 위해 executeOperation() 이 구현되어있는경우
B컨트랙트가 flashloan() 에 receiverAddress 파라미터로 A컨트랙트 주소를 넣고 실행할 수 있습니다.
이 경우 A컨트랙트의 executeOperation() 가 실행 될 것이고, 클레이뱅크의 LendingPool은 A컨트랙트로부터 자산 회수를 시도합니다.
A컨트랙트에 자산이 있기때문에 자산회수가 성공하게되고 A컨트랙트 코드에 따라 자산손실이 발생할 수 있습니다.
이 공격을 막기위해서 executeOperation 함수에 적절한 방어로직(initiator 화이트리스팅, 자산 전,후 비교 require문 등..)을 충분히 고려하는것을 권장합니다.
활용방안
클레이 뱅크의 플래시론을 활용하여 순간 큰 자산이 필요할 때 기능을 수행할 수 있습니다.
클레이튼 내 DEX내에서의 큰 규모의 차액거래(Arbitrage) 기회가 생겼을때 활용하여 차액을 획득할 수 있으며
클레이뱅크 뿐만아니라 다른 대출 프로토콜들의 청산기회가 생겼을때 없는 자산을 빌려 청산을 진행하고 청산 보너스를 얻을 수 있습니다.
이 외 한 트랜잭션내에 큰 규모의 자산을 빌려 이득을 취할수 상황이 있다면 플래시론을 활용하여 큰 이익을 얻을 수 있습니다.