---
# System prepended metadata

title: Shuttle Issues

---

[GasStation]
질문.
- 1 체인(터미널) 당 1 가스스테이션만 가능하고, 1 가스스테이션 당 1 버퍼만 가능한게 맞나? 셔틀마다 원하는 buffer 를 설정할 수 있게 gasStation 을 여러개 두든지, gasStation 을 수정하든지 해야함?

> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/a94898cfe8db08aab149c8154522c90fffc695bb

> gasStation 수정. 체인id 별로 버퍼가 여러개 가능. 리워드도 체인id별로 따로 관리. claim buffer 할때 맞는곳 찾아감.
 
[LidoBuffer]
오류.
- receive() external payable {} 누락
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/718cc71f1e35c48df7365c89f098870bc83c9199
- yield() 에서 - liquidatedTotal 을 없애야 할 듯.
(1) 100 submit 하고 (stETH.bal : 100, ts : 100) (2) 시간지나 stETH 가 200 됨 (st:200, ts:100) (3)이때 yield 는 100 이고 여기서 70 만큼 liquidate 하면 stETH balance 는 130, ts 는 100. 이 경우 잔여 yield 는 30(stBal - ts) 이어야지 여기서 liquidatedTotal 까지 빼주면 -40으로 underflow.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/c0dbacb0feb75e88941c63c513ef4411584d044b

질문.
- IBufferLiquidator(liquidator).liquidate(amount)
여기서 liquidator 는 stETH 를 ETH 로 바꿔주는 애지? amount 만큼의 stETH 를 슬리피지 고려해서 충분한 양의 ETH 로 바꿔주는 것. 근데 이건 주기적으로 누가 따로 해줘야하는디?

> 누구나 언제든 할 수 있고 MINIMUM_SLIPPAGE_TOLERANCE 이상의 차액은 청산자의 수익이 됨
- liquidationRatio 의 필요성? (걍 100% 면 안됨?)
> 프로토콜에 항상 일정한 stETH가 남아있어서 수익을 극대화하기 위함 : 이따 통화하자.(TODO)
> - [x] 수정 필요 (수식이 잘못됨)


[ShuttleDepartures]
오류.
- CANCEL_CHECK_IN_WAITING 지났을 때, amountMin 은 넘었는데 accountsMin 이 못 넘은 경우. checkIn, send, cancel 모두 불가.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/f0edb8dc73744d58b92e906bc33c43e676ce0969
> cancel 은 2일로 바꾸고. 2일지나면 무조건 cancel.
- amountMin 도 다 찼고, accountsMin 도 다 찼더라도, cancel 이 필수적일때도 있음. operator 에 문제가 생기거나, dst전략에 문제가 생기거나, 파람이 잘못들어갔거나... 이때 대응이 불가능함. 일단 보내고 반환해서 취소하는게 말이 안되는듯. 불가능할수도 있고.
> 이건 어쩔수 없이 보내고 반환해서 취소해야함, 최대한 취소가 불가능하게 하는게 마키의 의도임
- 1주일이 지나도 출발 못하면 출발 불가능해지고 무조건 취소 가능한 super_cancel_limit 같은거 넣으면 어떰?
> 애초에 이런 가능성을 안 만들고 사람들이 더 많이 참여하는게 만드는 게 마키의 의도임
- fee = Math.min((feeToPay * amount) / (reservation.amountMin - totalAmount), feeToPay) 수식 분모 잘못됨.
amountMin 이 200 이고, reserve 가 100. 1st checkIn 이 50. 2nd checkIn 이 50일 때. (0->100->150->200)
reserver가 1/2 * totalFee 를 내고, 1st 유저가 1/2 totalFee 를 내고, 2nd 유저는 공짜. 분모가 이상함.
> ✅ 검토 결과 올바른 수식임. feeToPay 자체가 totalFee - feePaid이고 _totalAmount는 이번 금액을 납부하기 이전까지의 총 금액임.
> totalFee가 동일하다는 가정하에, reserver가 1/2 * totalFee를 내고, 1st 유저가 1/2 * 1/2 * totalFee를 내고, 2nd 유저는 1 * 1/4 * totalFee를 내는 식으로 진행됨.
> 
> 나도 재검토 TODO
- payFee 추가 검토 필요.

질문.
- operator 를 제거할 일은 없나?
> 제거해버리면 리턴 오퍼레이터로 지정된 셔틀이 리턴이 불가능해질 수도 있기 때문에 오퍼레이터에 문제가 있으면 프론트엔드에서 선택 못하는 식으로 하면 될듯
- reserveShuttle 에 if (reservation.amountMin < amount) revert InvalidAmount()
필요성? 이게 1명이 자기거만 싸게 보내지 못하게 하기위함? 어차피 accountsMin 때문에 안됨. reserve/checkIn 2번 시행으로 어차피 우회 가능.
> - [x] https://github.com/lz-asia/shuttle/commit/3facbc7c05cd843d20731bf432e98bc281adedd5
- reserve 할 때 리턴기능 열어두는게 필수? 반대쪽에서는 depositOrReturn 무조건 실행할거?
> 리턴기능을 없애야 한다는 건지 질문의 의도를 모르겠음
- _sendShuttle 에서 (reservation.dstGasLimit + dstExtraGas) 이부분. operator 의 minDstGasLookup[dstChainId][PT_SEND_SHUTTLE] 에 더하는게 맞나?
> minDstGasLoopup은 너무 적은 가스를 입력하는 것을 방지하기 위함이고 dstExtraGas 는 확실하게 충분한 가스를 추가해서 도착하자마자 바로 deposit 할 수 있기 위한 기능임


[ShuttleArrivals]
오류.
- onShuttleArrived, onShuttleReturned 에서 revert 나면, 토큰은 operator 에 잔류하고, airdrop 가스도 operator 에 잔류. clearCachedSwap 으로 시도해야되는데, 이후 100% 실패하는 경우에는 대책 없음.
해당 registry 등록이 그 사이에 해제됐을 수도 있고, initialize 에서 실패할수도 있고..
> 그래서 register 등록 해제하는데 하루가 걸림(물론 완벽한건 아님), 100% 실패하는 경우는 또 어떤게 있을까?
> - [x] Shuttle.initialize() 내에서 try IGasStation().enter() 하는 방향으로 수정 https://github.com/lz-asia/shuttle/commit/66c6278847f1886d3377eb07255fd966b62e0e38


[ShuttleTerminal]
오류.
- mintRemote, withdrawRemote, redeemRemote, customCallRemote, claimRemote 가 dstChain 에서 revert 났을 때, 나중에 그 조건 그대로 retryMessage 가능하지만, native coin 에어드랍도 겸할 시 eth 는 terminal에 잔류. 다음 콜 왔을때 그대로 가져감.
> - [x] 네이티브 에어드랍을 삭제하는 방향으로 수정 https://github.com/lz-asia/shuttle/commit/fd8b10bf85badcb2c61098b517d5e86e6c21c0bb

질문.
- 왜 customCall 시리즈만 dstGasLimit 을 씀? 나머지는 dstExtraGas 인데...
> PT_CUSTOM_CALL 은 minDstGasLookup 을 설정 안해줄 예정임 (커스텀 콜이라 최소 얼마의 가스가 필요한지 알수가 없음)



[StargateOperator]
오류.
- remoteLookup 에 dstCHainId 오기.
> - [x] 수정 필요
- sgReceive 실패할 경우, 대책 마련 필요. 토큰은 StargateOperator 에 잔류하고, StargateRouter 에 cachedSwapLookup 으로 저장됨. 다만 retry 가 무조건 실패할 경우에는?
> 위에서 언급된 것처럼 Shuttle.initialize()에서 try catch 넣는 방향으로 수정




[Shuttle]
오류.
- _deposit 에서 _approveReceiptTokens 가 반드시 발생하는데, approve 가 불가능한 경우도 있을 듯. IERC20(token).approve(_strategy, type(uint256).max) 를 try-catch 로 하는것이 어떨까.
> - [x] approve 자체를 Shuttle 에서 제외하는 방향으로 수정
- mint,redeem,withdraw,claim,customCall 모두에서 to 가 address(0) 인지를 확인하는데, 이거는 src터미널에(도) 넣는게 좋을 듯.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/1b93cbbe8006456732dabe9c9816daee5ff37e94
- _withdraw 에서 amountWithdrawn = abi.decode(data, (uint256)) 이후 withdrawnAll = true 필요.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/e3047f5126ad5104f2de4bb1bce98cfcee10343b
- _withdraw 에서 amount = (amountWithdrawn * shares) / _totalShares 이후 amountWithdrawn -= amount 필요.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/5e3bb77cda4b097b5b74192fb6d7f26a398c24b1
- claim 에 sharesOf[tokenId] 가 0이면 리버트 넣으면 좋을 듯.
> 수정 필요없음
- _claim 과 _update 에서 rewardToken 이 NativeCoin 일 수도 있는데 고려 안되어 있음.
> - [x] nativeCoin과 ERC20 모두 지원하는 방향으로 수정 https://github.com/lz-asia/shuttle/commit/4909ea54670ed9c31a2c14e9fc34a0b07325642a
> - [x] ShuttleTerminal.airdropNative()를 추가 https://github.com/lz-asia/shuttle/commit/92b9b1f8db3192b76f49f213b09017cf6b6aa52f
> - [x] Vault 계약 추가(MinimalProxy; 스왑 후 cross-chain transfer 가능한 함수 지원) https://github.com/lz-asia/shuttle/commit/f51f2259f6691a13f5dfb3c57c71cd000c755d98
- _update 의 계산식이 이상한듯. _update 호출 이후, reward 의 transfer 가 이루어져 그 balance 가 줄어들면 reserves 도 수정되어야 하지 않나 싶은데...
> 수정함 
- _claim 과 _update 에서 rewardToken 이 asset 과 같은 경우도 있어 고려해줘야함.
> 더 고려해봐야함 🧠

큼직하게,
claim 시 reward 로 native coin 또는 asset 과 동일한 token 이 올 수도 있음. (Redacted 참고.)
withdraw 시, withdrawAll 로 전부 인출할 수 있음. (이경우 reward 도 일괄 수령.)
reward 와 asset 이 동일한 경우,
withdrawAll 이면 구분안해도 됨.
본인 것만 인출하는 withdraw 의 경우, 본인 몫의 asset + 전체 몫의 reward 가 들어올 수 있음. 이러면 복잡해짐. 구분필요.
> - [x] 수정 필요 (기존 코드로도 문제없이 동작)

- customCall 에서 args가 아무거나 들어오면 문제됨. 현재 customCall 이 사용될 주된 예시가 withdraw(혹은 claim)가 2번의 트랜잭션이 필요한 경우. 이러면 totalShare, 본인 share 정보를 포함해서 모두 넘겨야 할 듯.
- customCall 을 2번 호출하는데, 예를들면 첫번째는 initiateWithdraw 라서 토큰 등 아무런 반환이 없고, 두번째는 executeWithdraw 라서 asset(본인 몫일 수도 있고, withdrawAll 이라서 전체 몫일 수도 있음) 과 reward(전체 몫)를 돌려주는게 구현되어야함.

> - [x] customCall 제거 https://github.com/lz-asia/shuttle/commit/12e8b98090cc36a8b9e5d03ded34669ed5e416f6

- depositOrReturn 에서 returnShuttle 호출 시, address(this).balance+msg.value 로 입력되어있는데, 현재 msg 의 msg.value 를 합친 값이 address(this).balance 임. 그냥 address(this) 를 써야 함.
> - [x] 수정 필요 https://github.com/lz-asia/shuttle/commit/f6bcd810e8f05a6c3cad05c1e1979e78330fa99e

## TODO
- [ ] 체크인 할 때 전체 수수료를 한번에 내서 바로 출발이 잘 되는지 테스트
- [ ] Shuttle 보낼 때 셰어 정보 10^18로 정규화 해야함?
- [ ] Shuttle 도착 실패한 경우, 리턴이 잘 되는지 테스트
- [ ] ShuttleTerminal.sendNative() 호출 후 Vault.transferXXX() 호출 통해 (필요하다면 스왑 후) 다른 체인으로 토큰이 잘 이동하는지 테스트
- [ ] Buffer에 금액이 있을 때 일드 파밍이 잘 되는지 테스트
- [ ] 실제 서비스될 Strategy을 이용한 전체 과정 테스트