Skip to content

Commit

Permalink
Move things around a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
hayesgm committed Nov 20, 2024
1 parent b79aa47 commit 713238f
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 164 deletions.
2 changes: 1 addition & 1 deletion src/builder/actions/Actions.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity ^0.8.27;

import {console} from "../console.sol";
import {console} from "src/builder/console.sol";

import {Accounts} from "src/builder/Accounts.sol";
import {Across, BridgeRoutes, CCTP} from "src/builder/BridgeRoutes.sol";
Expand Down
157 changes: 157 additions & 0 deletions test/builder/BridgingLogic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,161 @@ contract BridgingLogicTest is Test, QuarkBuilderTest {
assertNotEq(result.eip712Data.domainSeparator, hex"", "non-empty domain separator");
assertNotEq(result.eip712Data.hashStruct, hex"", "non-empty hashStruct");
}

function testSimpleBridgeWithAcrossTransferSucceeds() public {
QuarkBuilder builder = new QuarkBuilder();
// Note: There are 3e6 USDC on each chain, so the Builder should attempt to bridge 2 USDC to chain 8453
QuarkBuilder.BuilderResult memory result = builder.transfer(
TransferActionsBuilder.TransferIntent({
assetSymbol: "USDC",
chainId: 8453,
amount: 5e6,
sender: address(0xb0b),
recipient: address(0xceecee),
blockTimestamp: BLOCK_TIMESTAMP,
preferAcross: true
}), // transfer 5 USDC on chain 8453 to 0xceecee
chainAccountsList_(6e6), // holding 6 USDC in total across chains 1, 8453
paymentUsd_()
);

assertEq(result.paymentCurrency, "usd", "usd currency");

// Check the quark operations
assertEq(result.quarkOperations.length, 2, "two operations");
assertEq(
result.quarkOperations[0].scriptAddress,
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
/* codeJar address */
address(CodeJarHelper.CODE_JAR_ADDRESS),
uint256(0),
/* script bytecode */
keccak256(type(AcrossActions).creationCode)
)
)
)
)
),
"script address for bridge action is correct given the code jar address"
);
assertEq(
result.quarkOperations[0].scriptCalldata,
abi.encodeCall(
AcrossActions.depositV3,
(
0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5, // spokePool
address(0xb0b), // depositor
address(0xb0b), // recipient
address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), // inputToken
address(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913), // outputToken
0x2e14e0, // inputAmount
0x1e8480, // outputAmount
8453, // destinationChainId
address(0), // exclusiveRelayer
uint32(BLOCK_TIMESTAMP) - 30 seconds, // quoteTimestamp
uint32(BLOCK_TIMESTAMP + 10 minutes), // fillDeadline
0, // exclusivityDeadline
new bytes(0), // message
false // useNativeToken
)
),
"calldata is AcrossActions.depositV3(...);"
);
assertEq(
result.quarkOperations[0].expiry, BLOCK_TIMESTAMP + 7 days, "expiry is current blockTimestamp + 7 days"
);
assertEq(result.quarkOperations[0].nonce, ALICE_DEFAULT_SECRET, "unexpected nonce");
assertEq(result.quarkOperations[0].isReplayable, false, "isReplayable is false");

assertEq(
result.quarkOperations[1].scriptAddress,
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
/* codeJar address */
address(CodeJarHelper.CODE_JAR_ADDRESS),
uint256(0),
/* script bytecode */
keccak256(type(TransferActions).creationCode)
)
)
)
)
),
"script address for transfer is correct given the code jar address"
);
assertEq(
result.quarkOperations[1].scriptCalldata,
abi.encodeCall(TransferActions.transferERC20Token, (usdc_(8453), address(0xceecee), 5e6)),
"calldata is TransferActions.transferERC20Token(USDC_8453, address(0xceecee), 5e6);"
);
assertEq(
result.quarkOperations[1].expiry, BLOCK_TIMESTAMP + 7 days, "expiry is current blockTimestamp + 7 days"
);
assertEq(result.quarkOperations[1].nonce, BOB_DEFAULT_SECRET, "unexpected nonce");
assertEq(result.quarkOperations[1].isReplayable, false, "isReplayable is false");

// Check the actions
assertEq(result.actions.length, 2, "two actions");
assertEq(result.actions[0].chainId, 1, "operation is on chainid 1");
assertEq(result.actions[0].quarkAccount, address(0xa11ce), "0xa11ce sends the funds");
assertEq(result.actions[0].actionType, "BRIDGE", "action type is 'BRIDGE'");
assertEq(result.actions[0].paymentMethod, "OFFCHAIN", "payment method is 'OFFCHAIN'");
assertEq(result.actions[0].paymentToken, address(0), "payment token is null");
assertEq(result.actions[0].paymentMaxCost, 0, "payment has no max cost, since 'OFFCHAIN'");
assertEq(result.actions[0].nonceSecret, ALICE_DEFAULT_SECRET, "unexpected nonce secret");
assertEq(result.actions[0].totalPlays, 1, "total plays is 1");
assertEq(
result.actions[0].actionContext,
abi.encode(
Actions.BridgeActionContext({
price: USDC_PRICE,
token: USDC_1,
assetSymbol: "USDC",
inputAmount: 0x2e14e0,
outputAmount: 0x1e8480,
chainId: 1,
recipient: address(0xb0b),
destinationChainId: 8453,
bridgeType: Actions.BRIDGE_TYPE_ACROSS
})
),
"action context encoded from BridgeActionContext"
);
assertEq(result.actions[1].chainId, 8453, "operation is on chainid 8453");
assertEq(result.actions[1].quarkAccount, address(0xb0b), "0xb0b sends the funds");
assertEq(result.actions[1].actionType, "TRANSFER", "action type is 'TRANSFER'");
assertEq(result.actions[1].paymentMethod, "OFFCHAIN", "payment method is 'OFFCHAIN'");
assertEq(result.actions[1].paymentToken, address(0), "payment token is null");
assertEq(result.actions[1].paymentMaxCost, 0, "payment has no max cost, since 'OFFCHAIN'");
assertEq(result.actions[1].nonceSecret, BOB_DEFAULT_SECRET, "unexpected nonce secret");
assertEq(result.actions[1].totalPlays, 1, "total plays is 1");
assertEq(
result.actions[1].actionContext,
abi.encode(
Actions.TransferActionContext({
amount: 5e6,
price: USDC_PRICE,
token: USDC_8453,
assetSymbol: "USDC",
chainId: 8453,
recipient: address(0xceecee)
})
),
"action context encoded from TransferActionContext"
);

// TODO: Check the contents of the EIP712 data
assertNotEq(result.eip712Data.digest, hex"", "non-empty digest");
assertNotEq(result.eip712Data.domainSeparator, hex"", "non-empty domain separator");
assertNotEq(result.eip712Data.hashStruct, hex"", "non-empty hashStruct");
}
}
163 changes: 0 additions & 163 deletions test/builder/QuarkBuilderTransfer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ import {FFI} from "src/builder/FFI.sol";
import {AcrossFFI} from "test/builder/mocks/AcrossFFI.sol";

contract QuarkBuilderTransferTest is Test, QuarkBuilderTest {
function setUp() public {
// Deploy mock FFI for calling Across API
AcrossFFI mockFFI = new AcrossFFI();
vm.etch(FFI.ACROSS_FFI_ADDRESS, address(mockFFI).code);
}

function transferUsdc_(uint256 chainId, uint256 amount, address recipient, uint256 blockTimestamp)
internal
pure
Expand Down Expand Up @@ -455,163 +449,6 @@ contract QuarkBuilderTransferTest is Test, QuarkBuilderTest {
assertNotEq(result.eip712Data.hashStruct, hex"", "non-empty hashStruct");
}

function testSimpleBridgeWithAcrossTransferSucceeds() public {
QuarkBuilder builder = new QuarkBuilder();
// Note: There are 3e6 USDC on each chain, so the Builder should attempt to bridge 2 USDC to chain 8453
QuarkBuilder.BuilderResult memory result = builder.transfer(
transferToken_({
assetSymbol: "USDC",
chainId: 8453,
amount: 5e6,
sender: address(0xb0b),
recipient: address(0xceecee),
blockTimestamp: BLOCK_TIMESTAMP,
preferAcross: true
}), // transfer 5 USDC on chain 8453 to 0xceecee
chainAccountsList_(6e6), // holding 6 USDC in total across chains 1, 8453
paymentUsd_()
);

assertEq(result.paymentCurrency, "usd", "usd currency");

// Check the quark operations
assertEq(result.quarkOperations.length, 2, "two operations");
assertEq(
result.quarkOperations[0].scriptAddress,
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
/* codeJar address */
address(CodeJarHelper.CODE_JAR_ADDRESS),
uint256(0),
/* script bytecode */
keccak256(type(AcrossActions).creationCode)
)
)
)
)
),
"script address for bridge action is correct given the code jar address"
);
assertEq(
result.quarkOperations[0].scriptCalldata,
abi.encodeCall(
AcrossActions.depositV3,
(
0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5, // spokePool
address(0xb0b), // depositor
address(0xb0b), // recipient
address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), // inputToken
address(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913), // outputToken
0x2e14e0, // inputAmount
0x1e8480, // outputAmount
8453, // destinationChainId
address(0), // exclusiveRelayer
uint32(BLOCK_TIMESTAMP) - 30 seconds, // quoteTimestamp
uint32(BLOCK_TIMESTAMP + 10 minutes), // fillDeadline
0, // exclusivityDeadline
new bytes(0), // message
false // useNativeToken
)
),
"calldata is AcrossActions.depositV3(...);"
);
assertEq(
result.quarkOperations[0].expiry, BLOCK_TIMESTAMP + 7 days, "expiry is current blockTimestamp + 7 days"
);
assertEq(result.quarkOperations[0].nonce, ALICE_DEFAULT_SECRET, "unexpected nonce");
assertEq(result.quarkOperations[0].isReplayable, false, "isReplayable is false");

assertEq(
result.quarkOperations[1].scriptAddress,
address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
/* codeJar address */
address(CodeJarHelper.CODE_JAR_ADDRESS),
uint256(0),
/* script bytecode */
keccak256(type(TransferActions).creationCode)
)
)
)
)
),
"script address for transfer is correct given the code jar address"
);
assertEq(
result.quarkOperations[1].scriptCalldata,
abi.encodeCall(TransferActions.transferERC20Token, (usdc_(8453), address(0xceecee), 5e6)),
"calldata is TransferActions.transferERC20Token(USDC_8453, address(0xceecee), 5e6);"
);
assertEq(
result.quarkOperations[1].expiry, BLOCK_TIMESTAMP + 7 days, "expiry is current blockTimestamp + 7 days"
);
assertEq(result.quarkOperations[1].nonce, BOB_DEFAULT_SECRET, "unexpected nonce");
assertEq(result.quarkOperations[1].isReplayable, false, "isReplayable is false");

// Check the actions
assertEq(result.actions.length, 2, "two actions");
assertEq(result.actions[0].chainId, 1, "operation is on chainid 1");
assertEq(result.actions[0].quarkAccount, address(0xa11ce), "0xa11ce sends the funds");
assertEq(result.actions[0].actionType, "BRIDGE", "action type is 'BRIDGE'");
assertEq(result.actions[0].paymentMethod, "OFFCHAIN", "payment method is 'OFFCHAIN'");
assertEq(result.actions[0].paymentToken, address(0), "payment token is null");
assertEq(result.actions[0].paymentMaxCost, 0, "payment has no max cost, since 'OFFCHAIN'");
assertEq(result.actions[0].nonceSecret, ALICE_DEFAULT_SECRET, "unexpected nonce secret");
assertEq(result.actions[0].totalPlays, 1, "total plays is 1");
assertEq(
result.actions[0].actionContext,
abi.encode(
Actions.BridgeActionContext({
price: USDC_PRICE,
token: USDC_1,
assetSymbol: "USDC",
inputAmount: 0x2e14e0,
outputAmount: 0x1e8480,
chainId: 1,
recipient: address(0xb0b),
destinationChainId: 8453,
bridgeType: Actions.BRIDGE_TYPE_ACROSS
})
),
"action context encoded from BridgeActionContext"
);
assertEq(result.actions[1].chainId, 8453, "operation is on chainid 8453");
assertEq(result.actions[1].quarkAccount, address(0xb0b), "0xb0b sends the funds");
assertEq(result.actions[1].actionType, "TRANSFER", "action type is 'TRANSFER'");
assertEq(result.actions[1].paymentMethod, "OFFCHAIN", "payment method is 'OFFCHAIN'");
assertEq(result.actions[1].paymentToken, address(0), "payment token is null");
assertEq(result.actions[1].paymentMaxCost, 0, "payment has no max cost, since 'OFFCHAIN'");
assertEq(result.actions[1].nonceSecret, BOB_DEFAULT_SECRET, "unexpected nonce secret");
assertEq(result.actions[1].totalPlays, 1, "total plays is 1");
assertEq(
result.actions[1].actionContext,
abi.encode(
Actions.TransferActionContext({
amount: 5e6,
price: USDC_PRICE,
token: USDC_8453,
assetSymbol: "USDC",
chainId: 8453,
recipient: address(0xceecee)
})
),
"action context encoded from TransferActionContext"
);

// TODO: Check the contents of the EIP712 data
assertNotEq(result.eip712Data.digest, hex"", "non-empty digest");
assertNotEq(result.eip712Data.domainSeparator, hex"", "non-empty domain separator");
assertNotEq(result.eip712Data.hashStruct, hex"", "non-empty hashStruct");
}

function testSimpleBridgeTransferWithPaycallSucceeds() public {
QuarkBuilder builder = new QuarkBuilder();
PaymentInfo.PaymentMaxCost[] memory maxCosts = new PaymentInfo.PaymentMaxCost[](2);
Expand Down

0 comments on commit 713238f

Please sign in to comment.