From cd4998699041c734847865be17564ca6dd6e7f23 Mon Sep 17 00:00:00 2001 From: placeholder Date: Wed, 5 Jun 2024 13:05:29 -0700 Subject: [PATCH 1/6] Add CCTP Bridger --- src/DeFiScripts.sol | 14 ++++++ src/interfaces/ITokenMessenger.sol | 8 ++++ test/CCTPBridge.t.sol | 70 ++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 src/interfaces/ITokenMessenger.sol create mode 100644 test/CCTPBridge.t.sol diff --git a/src/DeFiScripts.sol b/src/DeFiScripts.sol index 1d73b1d2..8eb8ee30 100644 --- a/src/DeFiScripts.sol +++ b/src/DeFiScripts.sol @@ -9,6 +9,7 @@ import {QuarkScript} from "quark-core/src/QuarkScript.sol"; import {IComet} from "./interfaces/IComet.sol"; import {ICometRewards} from "./interfaces/ICometRewards.sol"; +import {ITokenMessenger} from "./interfaces/ITokenMessenger.sol"; import {DeFiScriptErrors} from "./lib/DeFiScriptErrors.sol"; contract CometSupplyActions { @@ -326,3 +327,16 @@ contract ApproveAndSwap { IERC20(sellToken).forceApprove(to, 0); } } + +contract CCTPBridgeActions { + function bridgeUSDC( + address tokenMessenger, + uint256 amount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken + ) external { + IERC20(burnToken).approve(tokenMessenger, amount); + ITokenMessenger(tokenMessenger).depositForBurn(amount, destinationDomain, mintRecipient, burnToken); + } +} diff --git a/src/interfaces/ITokenMessenger.sol b/src/interfaces/ITokenMessenger.sol new file mode 100644 index 00000000..99c94ed1 --- /dev/null +++ b/src/interfaces/ITokenMessenger.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.23; + +interface ITokenMessenger { + function depositForBurn(uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken) + external + returns (uint64 _nonce); +} diff --git a/test/CCTPBridge.t.sol b/test/CCTPBridge.t.sol new file mode 100644 index 00000000..ebe49945 --- /dev/null +++ b/test/CCTPBridge.t.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.23; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "forge-std/StdUtils.sol"; +import "forge-std/StdMath.sol"; + +import {CodeJar} from "codejar/src/CodeJar.sol"; + +import {QuarkWallet} from "quark-core/src/QuarkWallet.sol"; +import {QuarkStateManager} from "quark-core/src/QuarkStateManager.sol"; + +import {QuarkWalletProxyFactory} from "quark-proxy/src/QuarkWalletProxyFactory.sol"; + +import {YulHelper} from "./lib/YulHelper.sol"; +import {SignatureHelper} from "./lib/SignatureHelper.sol"; +import {QuarkOperationHelper, ScriptType} from "./lib/QuarkOperationHelper.sol"; + +import "src/DeFiScripts.sol"; + +/** + * Tests for CCTP Bridge + */ +contract CCTPBridge is Test { + QuarkWalletProxyFactory public factory; + uint256 alicePrivateKey = 0xa11ce; + address alice = vm.addr(alicePrivateKey); + + // Contracts address on mainnet + address constant tokenMessenger = 0xBd3fa81B58Ba92a82136038B25aDec7066af3155; + address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + // Domain value for the CCTP bridge, DIFFERENT from chain id + uint32 constant mainnetDomain = 0; + uint32 constant baseDomain = 6; + + function setUp() public { + // Fork setup + vm.createSelectFork( + string.concat( + "https://node-provider.compound.finance/ethereum-mainnet/", vm.envString("NODE_PROVIDER_BYPASS_KEY") + ), + 18429607 // 2023-10-25 13:24:00 PST + ); + factory = new QuarkWalletProxyFactory(address(new QuarkWallet(new CodeJar(), new QuarkStateManager()))); + } + + function testBridgeToBase() public { + vm.pauseGasMetering(); + QuarkWallet wallet = QuarkWallet(factory.create(alice, address(0))); + bytes memory cctpBridgeScript = new YulHelper().getCode("DeFiScripts.sol/CCTPBridgeActions.json"); + + deal(USDC, address(wallet), 1_000_000e6); + + QuarkWallet.QuarkOperation memory op = new QuarkOperationHelper().newBasicOpWithCalldata( + wallet, + cctpBridgeScript, + abi.encodeCall( + CCTPBridgeActions.bridgeUSDC, + (tokenMessenger, 500_000e6, 6, bytes32(uint256(uint160(address(wallet)))), USDC) + ), + ScriptType.ScriptSource + ); + (uint8 v, bytes32 r, bytes32 s) = new SignatureHelper().signOp(alicePrivateKey, wallet, op); + assertEq(IERC20(USDC).balanceOf(address(wallet)), 1_000_000e6); + vm.resumeGasMetering(); + wallet.executeQuarkOperation(op, v, r, s); + assertEq(IERC20(USDC).balanceOf(address(wallet)), 500_000e6); + } +} From 8570515433c0ed9cbd752c3a2bd6392e494f90ae Mon Sep 17 00:00:00 2001 From: placeholder Date: Wed, 5 Jun 2024 13:25:29 -0700 Subject: [PATCH 2/6] snapshot --- .gas-snapshot | 1 + 1 file changed, 1 insertion(+) diff --git a/.gas-snapshot b/.gas-snapshot index 9d84617e..8d99b218 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,6 +1,7 @@ ApproveAndSwapTest:testSwap() (gas: 285500) ApproveAndSwapTest:testSwapFailsIfWeExpectedTooMuch() (gas: 364666) ApproveAndSwapTest:testSwapFailsWithNoApproval() (gas: 122231) +CCTPBridge:testBridgeToBase() (gas: 146874) CometClaimRewardsTest:testClaimComp() (gas: 131265) CometRepayAndWithdrawMultipleAssetsTest:testInvalidInput() (gas: 68171) CometRepayAndWithdrawMultipleAssetsTest:testRepayAndWithdrawMultipleAssets() (gas: 153860) From b2da873a0664517cbf20c44f9b62efa4de314f4a Mon Sep 17 00:00:00 2001 From: placeholder Date: Wed, 5 Jun 2024 14:04:09 -0700 Subject: [PATCH 3/6] address comment --- src/BridgeScripts.sol | 18 ++++++++++++++++++ src/DeFiScripts.sol | 15 +-------------- ...CTPBridge.t.sol => CCTPBridgeActions.t.sol} | 4 ++-- 3 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 src/BridgeScripts.sol rename test/{CCTPBridge.t.sol => CCTPBridgeActions.t.sol} (97%) diff --git a/src/BridgeScripts.sol b/src/BridgeScripts.sol new file mode 100644 index 00000000..72a7d982 --- /dev/null +++ b/src/BridgeScripts.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.23; + +import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; +import {ITokenMessenger} from "./interfaces/ITokenMessenger.sol"; + +contract CCTPBridgeActions { + function bridgeUSDC( + address tokenMessenger, + uint256 amount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken + ) external { + IERC20(burnToken).approve(tokenMessenger, amount); + ITokenMessenger(tokenMessenger).depositForBurn(amount, destinationDomain, mintRecipient, burnToken); + } +} \ No newline at end of file diff --git a/src/DeFiScripts.sol b/src/DeFiScripts.sol index 8eb8ee30..e703cbde 100644 --- a/src/DeFiScripts.sol +++ b/src/DeFiScripts.sol @@ -326,17 +326,4 @@ contract ApproveAndSwap { // Approvals to external contracts should always be reset to 0 IERC20(sellToken).forceApprove(to, 0); } -} - -contract CCTPBridgeActions { - function bridgeUSDC( - address tokenMessenger, - uint256 amount, - uint32 destinationDomain, - bytes32 mintRecipient, - address burnToken - ) external { - IERC20(burnToken).approve(tokenMessenger, amount); - ITokenMessenger(tokenMessenger).depositForBurn(amount, destinationDomain, mintRecipient, burnToken); - } -} +} \ No newline at end of file diff --git a/test/CCTPBridge.t.sol b/test/CCTPBridgeActions.t.sol similarity index 97% rename from test/CCTPBridge.t.sol rename to test/CCTPBridgeActions.t.sol index ebe49945..0681bc6a 100644 --- a/test/CCTPBridge.t.sol +++ b/test/CCTPBridgeActions.t.sol @@ -17,7 +17,7 @@ import {YulHelper} from "./lib/YulHelper.sol"; import {SignatureHelper} from "./lib/SignatureHelper.sol"; import {QuarkOperationHelper, ScriptType} from "./lib/QuarkOperationHelper.sol"; -import "src/DeFiScripts.sol"; +import "src/BridgeScripts.sol"; /** * Tests for CCTP Bridge @@ -48,7 +48,7 @@ contract CCTPBridge is Test { function testBridgeToBase() public { vm.pauseGasMetering(); QuarkWallet wallet = QuarkWallet(factory.create(alice, address(0))); - bytes memory cctpBridgeScript = new YulHelper().getCode("DeFiScripts.sol/CCTPBridgeActions.json"); + bytes memory cctpBridgeScript = new YulHelper().getCode("BridgeScripts.sol/CCTPBridgeActions.json"); deal(USDC, address(wallet), 1_000_000e6); From a4ed459ecd37df722f04e7a5a4c2aaf08f5090bc Mon Sep 17 00:00:00 2001 From: placeholder Date: Wed, 5 Jun 2024 14:05:34 -0700 Subject: [PATCH 4/6] add extra line --- test/CCTPBridgeActions.t.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CCTPBridgeActions.t.sol b/test/CCTPBridgeActions.t.sol index 0681bc6a..b82f1d3c 100644 --- a/test/CCTPBridgeActions.t.sol +++ b/test/CCTPBridgeActions.t.sol @@ -62,6 +62,7 @@ contract CCTPBridge is Test { ScriptType.ScriptSource ); (uint8 v, bytes32 r, bytes32 s) = new SignatureHelper().signOp(alicePrivateKey, wallet, op); + assertEq(IERC20(USDC).balanceOf(address(wallet)), 1_000_000e6); vm.resumeGasMetering(); wallet.executeQuarkOperation(op, v, r, s); From e82fe375cade305c74d4b27fb74785c0d89e839a Mon Sep 17 00:00:00 2001 From: placeholder Date: Wed, 5 Jun 2024 14:38:25 -0700 Subject: [PATCH 5/6] fmt --- src/BridgeScripts.sol | 2 +- src/DeFiScripts.sol | 2 +- test/CCTPBridgeActions.t.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BridgeScripts.sol b/src/BridgeScripts.sol index 72a7d982..cd223c08 100644 --- a/src/BridgeScripts.sol +++ b/src/BridgeScripts.sol @@ -15,4 +15,4 @@ contract CCTPBridgeActions { IERC20(burnToken).approve(tokenMessenger, amount); ITokenMessenger(tokenMessenger).depositForBurn(amount, destinationDomain, mintRecipient, burnToken); } -} \ No newline at end of file +} diff --git a/src/DeFiScripts.sol b/src/DeFiScripts.sol index e703cbde..1fda2c87 100644 --- a/src/DeFiScripts.sol +++ b/src/DeFiScripts.sol @@ -326,4 +326,4 @@ contract ApproveAndSwap { // Approvals to external contracts should always be reset to 0 IERC20(sellToken).forceApprove(to, 0); } -} \ No newline at end of file +} diff --git a/test/CCTPBridgeActions.t.sol b/test/CCTPBridgeActions.t.sol index b82f1d3c..933d528c 100644 --- a/test/CCTPBridgeActions.t.sol +++ b/test/CCTPBridgeActions.t.sol @@ -62,7 +62,7 @@ contract CCTPBridge is Test { ScriptType.ScriptSource ); (uint8 v, bytes32 r, bytes32 s) = new SignatureHelper().signOp(alicePrivateKey, wallet, op); - + assertEq(IERC20(USDC).balanceOf(address(wallet)), 1_000_000e6); vm.resumeGasMetering(); wallet.executeQuarkOperation(op, v, r, s); From 92b53460cf86292d7b1c388ed581df44e17258f2 Mon Sep 17 00:00:00 2001 From: Hans Wang Date: Wed, 5 Jun 2024 15:32:49 -0700 Subject: [PATCH 6/6] remove import: --- src/DeFiScripts.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DeFiScripts.sol b/src/DeFiScripts.sol index 1fda2c87..1d73b1d2 100644 --- a/src/DeFiScripts.sol +++ b/src/DeFiScripts.sol @@ -9,7 +9,6 @@ import {QuarkScript} from "quark-core/src/QuarkScript.sol"; import {IComet} from "./interfaces/IComet.sol"; import {ICometRewards} from "./interfaces/ICometRewards.sol"; -import {ITokenMessenger} from "./interfaces/ITokenMessenger.sol"; import {DeFiScriptErrors} from "./lib/DeFiScriptErrors.sol"; contract CometSupplyActions {