This README explains the steps I took and the reason I didn't fully achieve my goal for this last assignment. Due to the fact that I believe to have proved my compromise to the course and to have learned more than enough to be awarded the certificate of completion, along with the fact that I got married the week after the bootcamp, this was left unfinished. Nonetheless, I intend to find what the issue was after the summer, hopefully before the RWA bootcamp. Also, please bear in mind that I attempted to complete the exercise in a more complex way than expected when evaluating my work.
On the third and final day of the course the assignment was to measure the gas consumption of the _ccipReceive() function to then provide an accurate value to the transferUsdc() call on the contract we used on exercise 4.
Since for the aforementioned exercise the gas limit was 0, because we transferred the USDC to an EOA, this time we had to create a receiving contract. The resources linked in the assignment's description were a Chainlink Docs entry on how to estimate gas, and a Gitbook on how to deposit transferred USDC on Compound V3, following up on an exercise exactly like exercise 4. Looking at these, it seemed like following the whole Gitbook through in a test using CCIP Local Simulator in Forked Mode would be a great way to round up everything learnt throughout the course. Once the test were correctly configured, we would just have to take the gasUsed parameter of the MockCCIPRouter::MsgExecuted event, increase it by 10% and use that as the gasLimit parameter of the TransferUSDC::transferUsdc() function.
To do this, we wrote a comprehensive Foundry test you can see here, in which the following steps are followed (bear in mind that all of this happens locally, leveraging Forked CCIP Local Simulator):
- Deploy TransferUSDC.sol to Avalanche Fuji.
- Deploy CrossChainReceiver.sol and SwapTestnetUSDC.sol to Sepolia.
- Call
TransferUSDC::allowlistDestination()to make Sepolia an allowlisted chain. - Fund TransferUSDC.sol with 3 LINK to pay for CCIP fees.
- Approve TransferUSDC to move 1 USDC from the signer's EOA.
- Call
CrossChainReceiver::allowlistSourceChain()to make Fuji an allowlisted source chain for CCIP transfers. - Call
TransferUSDC::transferUsdc()to transfer 1 USDC from an EOA to the receiver contract. - Call
CCIPLocalSimulatorFork::switchChainAndRouteMessage()to route the CCIP message.
Following these steps, the MockCCIPRouter::MsgExecuted event, which looks as follows,
event MsgExecuted(bool success, bytes retData, uint256 gasUsed);should be emitted, giving us the gasUsed value we were looking for, to get an estimation of the gas consumption of the _ccipReceive() function in this use case.
However, the outcome wasn't as expected. The transaction went so far as to call EVM2EVMOffRamp::executeSingleMessage() on Sepolia, after burning the USDC token, by calling USDCTokenPool::lockOrBurn on Fuji but an unhandled revert was thrown upon calling IPool::releaseOrMint() (cannot be sure which contract exactly it is, because it is not verified on Sepolia Etherscan), as shown in the screenshot below:
Even the RateLimiter::TokenConsumed event got emitted for 1 USDC, but since the transaction didn't go through, the MockCCIPRouter::MsgExecuted event didn't get emitted, so we couldn't get the gas estimation we were looking for ☹
