Skip to content

Commit

Permalink
change param ordering in portal, split uniswap portal fns
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-kothari committed Sep 28, 2023
1 parent 9d51dc8 commit 2ecb9ea
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 191 deletions.
28 changes: 14 additions & 14 deletions l1-contracts/test/portals/TokenPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ contract TokenPortal {
// docs:start:deposit_public
/**
* @notice Deposit funds into the portal and adds an L2 message which can only be consumed publicly on Aztec
* @param _to - The aztec address of the recipient
* @param _amount - The amount to deposit
* @param _to - The aztec address of the recipient
* @param _canceller - The address that can cancel the L1 to L2 message
* @param _deadline - The timestamp after which the entry can be cancelled
* @param _secretHash - The hash of the secret consumable message. The hash should be 254 bits (so it can fit in a Field element)
* @param _canceller - The address that can cancel the L1 to L2 message
* @return The key of the entry in the Inbox
*/
function depositToAztecPublic(
bytes32 _to,
uint256 _amount,
bytes32 _to,
address _canceller,
uint32 _deadline,
bytes32 _secretHash,
address _canceller
bytes32 _secretHash
) external payable returns (bytes32) {
// Preamble
IInbox inbox = registry.getInbox();
Expand All @@ -59,18 +59,18 @@ contract TokenPortal {
/**
* @notice Deposit funds into the portal and adds an L2 message which can only be consumed privately on Aztec
* @param _amount - The amount to deposit
* @param _deadline - The timestamp after which the entry can be cancelled
* @param _secretHashForL2MessageConsumption - The hash of the secret consumable L1 to L2 message. The hash should be 254 bits (so it can fit in a Field element)
* @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element)
* @param _canceller - The address that can cancel the L1 to L2 message
* @param _deadline - The timestamp after which the entry can be cancelled
* @param _secretHashForL2MessageConsumption - The hash of the secret consumable L1 to L2 message. The hash should be 254 bits (so it can fit in a Field element)
* @return The key of the entry in the Inbox
*/
function depositToAztecPrivate(
uint256 _amount,
uint32 _deadline,
bytes32 _secretHashForL2MessageConsumption,
bytes32 _secretHashForRedeemingMintedNotes,
address _canceller
address _canceller,
uint32 _deadline,
bytes32 _secretHashForL2MessageConsumption
) external payable returns (bytes32) {
// Preamble
IInbox inbox = registry.getInbox();
Expand Down Expand Up @@ -99,16 +99,16 @@ contract TokenPortal {
/**
* @notice Cancel a public depositToAztec L1 to L2 message
* @dev only callable by the `canceller` of the message
* @param _to - The aztec address of the recipient in the original message
* @param _amount - The amount to deposit per the original message
* @param _to - The aztec address of the recipient in the original message
* @param _deadline - The timestamp after which the entry can be cancelled
* @param _secretHash - The hash of the secret consumable message in the original message
* @param _fee - The fee paid to the sequencer
* @return The key of the entry in the Inbox
*/
function cancelL1ToAztecMessagePublic(
bytes32 _to,
uint256 _amount,
bytes32 _to,
uint32 _deadline,
bytes32 _secretHash,
uint64 _fee
Expand Down Expand Up @@ -137,17 +137,17 @@ contract TokenPortal {
* @notice Cancel a private depositToAztec L1 to L2 message
* @dev only callable by the `canceller` of the message
* @param _amount - The amount to deposit per the original message
* @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec
* @param _deadline - The timestamp after which the entry can be cancelled
* @param _secretHashForL2MessageConsumption - The hash of the secret consumable L1 to L2 message
* @param _secretHashForL2MessageConsumption - The hash of the secret to redeem minted notes privately on Aztec
* @param _fee - The fee paid to the sequencer
* @return The key of the entry in the Inbox
*/
function cancelL1ToAztecMessagePrivate(
uint256 _amount,
bytes32 _secretHashForRedeemingMintedNotes,
uint32 _deadline,
bytes32 _secretHashForL2MessageConsumption,
bytes32 _secretHashForRedeemingMintedNotes,
uint64 _fee
) external returns (bytes32) {
IInbox inbox = registry.getInbox();
Expand Down
20 changes: 10 additions & 10 deletions l1-contracts/test/portals/TokenPortal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ contract TokenPortalTest is Test {
// Perform op
bytes32 entryKey = tokenPortal.depositToAztecPrivate{value: bid}(
amount,
deadline,
secretHashForL2MessageConsumption,
secretHashForRedeemingMintedNotes,
address(this)
address(this),
deadline,
secretHashForL2MessageConsumption
);

assertEq(entryKey, expectedEntryKey, "returned entry key and calculated entryKey should match");
Expand Down Expand Up @@ -185,7 +185,7 @@ contract TokenPortalTest is Test {

// Perform op
bytes32 entryKey = tokenPortal.depositToAztecPublic{value: bid}(
to, amount, deadline, secretHashForL2MessageConsumption, address(this)
amount, to, address(this), deadline, secretHashForL2MessageConsumption
);

assertEq(entryKey, expectedEntryKey, "returned entry key and calculated entryKey should match");
Expand All @@ -210,7 +210,7 @@ contract TokenPortalTest is Test {
abi.encodeWithSelector(Errors.Inbox__NothingToConsume.selector, expectedWrongEntryKey)
);
tokenPortal.cancelL1ToAztecMessagePublic(
to, amount, deadline, secretHashForL2MessageConsumption, bid
amount, to, deadline, secretHashForL2MessageConsumption, bid
);
vm.stopPrank();

Expand All @@ -221,7 +221,7 @@ contract TokenPortalTest is Test {
abi.encodeWithSelector(Errors.Inbox__NothingToConsume.selector, expectedWrongEntryKey)
);
tokenPortal.cancelL1ToAztecMessagePrivate(
amount, deadline, secretHashForL2MessageConsumption, secretHashForRedeemingMintedNotes, bid
amount, secretHashForRedeemingMintedNotes, deadline, secretHashForL2MessageConsumption, bid
);

// actually cancel the message
Expand All @@ -231,7 +231,7 @@ contract TokenPortalTest is Test {
emit L1ToL2MessageCancelled(expectedEntryKey);
// perform op
bytes32 entryKey = tokenPortal.cancelL1ToAztecMessagePublic(
to, amount, deadline, secretHashForL2MessageConsumption, bid
amount, to, deadline, secretHashForL2MessageConsumption, bid
);

assertEq(entryKey, expectedEntryKey, "returned entry key and calculated entryKey should match");
Expand All @@ -257,7 +257,7 @@ contract TokenPortalTest is Test {
abi.encodeWithSelector(Errors.Inbox__NothingToConsume.selector, expectedWrongEntryKey)
);
tokenPortal.cancelL1ToAztecMessagePrivate(
amount, deadline, secretHashForL2MessageConsumption, secretHashForRedeemingMintedNotes, bid
amount, secretHashForRedeemingMintedNotes, deadline, secretHashForL2MessageConsumption, bid
);
vm.stopPrank();

Expand All @@ -268,7 +268,7 @@ contract TokenPortalTest is Test {
abi.encodeWithSelector(Errors.Inbox__NothingToConsume.selector, expectedWrongEntryKey)
);
tokenPortal.cancelL1ToAztecMessagePublic(
to, amount, deadline, secretHashForL2MessageConsumption, bid
amount, to, deadline, secretHashForL2MessageConsumption, bid
);

// actually cancel the message
Expand All @@ -278,7 +278,7 @@ contract TokenPortalTest is Test {
emit L1ToL2MessageCancelled(expectedEntryKey);
// perform op
bytes32 entryKey = tokenPortal.cancelL1ToAztecMessagePrivate(
amount, deadline, secretHashForL2MessageConsumption, secretHashForRedeemingMintedNotes, bid
amount, secretHashForRedeemingMintedNotes, deadline, secretHashForL2MessageConsumption, bid
);

assertEq(entryKey, expectedEntryKey, "returned entry key and calculated entryKey should match");
Expand Down
132 changes: 103 additions & 29 deletions l1-contracts/test/portals/UniswapPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ contract UniswapPortal {

// docs:start:solidity_uniswap_swap
/**
* @notice Exit with funds from L2, perform swap on L1 and deposit output asset to L2 again
* @notice Exit with funds from L2, perform swap on L1 and deposit output asset to L2 again publicly
* @dev `msg.value` indicates fee to submit message to inbox. Currently, anyone can call this method on your behalf.
* They could call it with 0 fee causing the sequencer to never include in the rollup.
* In this case, you will have to cancel the message and then make the deposit later
Expand All @@ -45,26 +45,24 @@ contract UniswapPortal {
* @param _uniswapFeeTier - The fee tier for the swap on UniswapV3
* @param _outputTokenPortal - The ethereum address of the output token portal
* @param _amountOutMinimum - The minimum amount of output assets to receive from the swap (slippage protection)
* @param _aztecRecipientOrSecretHashForRedeemingMintedNotes - If public flow, the aztec address to receive the output assets. If private, the hash of the secret to redeem minted notes privately on Aztec.
* @param _secretHashForL1ToL2Message - The hash of the secret consumable message
* @param _aztecRecipient - The aztec address to receive the output assets
* @param _secretHashForL1ToL2Message - The hash of the secret consumable message. The hash should be 254 bits (so it can fit in a Field element)
* @param _deadlineForL1ToL2Message - deadline for when the L1 to L2 message (to mint outpiut assets in L2) must be consumed by
* @param _canceller - The ethereum address that can cancel the deposit
* @param _withCaller - When true, using `msg.sender` as the caller, otherwise address(0)
* @param _isPrivateFlow - When true, the output assets will be minted privately on Aztec, otherwise publicly
* @return The entryKey of the deposit transaction in the Inbox
*/
function swap(
function swapPublic(
address _inputTokenPortal,
uint256 _inAmount,
uint24 _uniswapFeeTier,
address _outputTokenPortal,
uint256 _amountOutMinimum,
bytes32 _aztecRecipientOrSecretHashForRedeemingMintedNotes,
bytes32 _aztecRecipient,
bytes32 _secretHashForL1ToL2Message,
uint32 _deadlineForL1ToL2Message,
address _canceller,
bool _withCaller,
bool _isPrivateFlow
bool _withCaller
) public payable returns (bytes32) {
LocalSwapVars memory vars;

Expand All @@ -75,22 +73,15 @@ contract UniswapPortal {
TokenPortal(_inputTokenPortal).withdraw(_inAmount, address(this), true);
{
// prevent stack too deep errors

// having two different hashes mean you can't consume a message intended for private in public.
string memory functionSignature = _isPrivateFlow
?
"swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,uint32,address,address)"
: "swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,uint32,address,address)";

vars.contentHash = Hash.sha256ToField(
abi.encodeWithSignature(
functionSignature,
"swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,uint32,address,address)",
_inputTokenPortal,
_inAmount,
_uniswapFeeTier,
_outputTokenPortal,
_amountOutMinimum,
_aztecRecipientOrSecretHashForRedeemingMintedNotes,
_aztecRecipient,
_secretHashForL1ToL2Message,
_deadlineForL1ToL2Message,
_canceller,
Expand Down Expand Up @@ -131,22 +122,105 @@ contract UniswapPortal {
vars.outputAsset.approve(address(_outputTokenPortal), amountOut);

// Deposit the output asset to the L2 via its portal
if (_isPrivateFlow) {
return TokenPortal(_outputTokenPortal).depositToAztecPrivate{value: msg.value}(
amountOut,
_deadlineForL1ToL2Message,
_secretHashForL1ToL2Message,
_aztecRecipientOrSecretHashForRedeemingMintedNotes,
_canceller
return TokenPortal(_outputTokenPortal).depositToAztecPublic{value: msg.value}(
amountOut, _aztecRecipient, _canceller, _deadlineForL1ToL2Message, _secretHashForL1ToL2Message
);
}
// docs:end:solidity_uniswap_swap

/**
* @notice Exit with funds from L2, perform swap on L1 and deposit output asset to L2 again privately
* @dev `msg.value` indicates fee to submit message to inbox. Currently, anyone can call this method on your behalf.
* They could call it with 0 fee causing the sequencer to never include in the rollup.
* In this case, you will have to cancel the message and then make the deposit later
* @param _inputTokenPortal - The ethereum address of the input token portal
* @param _inAmount - The amount of assets to swap (same amount as withdrawn from L2)
* @param _uniswapFeeTier - The fee tier for the swap on UniswapV3
* @param _outputTokenPortal - The ethereum address of the output token portal
* @param _amountOutMinimum - The minimum amount of output assets to receive from the swap (slippage protection)
* @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element)
* @param _secretHashForL1ToL2Message - The hash of the secret consumable message. The hash should be 254 bits (so it can fit in a Field element)
* @param _deadlineForL1ToL2Message - deadline for when the L1 to L2 message (to mint outpiut assets in L2) must be consumed by
* @param _canceller - The ethereum address that can cancel the deposit
* @param _withCaller - When true, using `msg.sender` as the caller, otherwise address(0)
* @return The entryKey of the deposit transaction in the Inbox
*/
function swapPrivate(
address _inputTokenPortal,
uint256 _inAmount,
uint24 _uniswapFeeTier,
address _outputTokenPortal,
uint256 _amountOutMinimum,
bytes32 _secretHashForRedeemingMintedNotes,
bytes32 _secretHashForL1ToL2Message,
uint32 _deadlineForL1ToL2Message,
address _canceller,
bool _withCaller
) public payable returns (bytes32) {
LocalSwapVars memory vars;

vars.inputAsset = TokenPortal(_inputTokenPortal).underlying();
vars.outputAsset = TokenPortal(_outputTokenPortal).underlying();

// Withdraw the input asset from the portal
TokenPortal(_inputTokenPortal).withdraw(_inAmount, address(this), true);
{
// prevent stack too deep errors
vars.contentHash = Hash.sha256ToField(
abi.encodeWithSignature(
"swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,uint32,address,address)",
_inputTokenPortal,
_inAmount,
_uniswapFeeTier,
_outputTokenPortal,
_amountOutMinimum,
_secretHashForRedeemingMintedNotes,
_secretHashForL1ToL2Message,
_deadlineForL1ToL2Message,
_canceller,
_withCaller ? msg.sender : address(0)
)
);
}
return TokenPortal(_outputTokenPortal).depositToAztecPublic{value: msg.value}(
_aztecRecipientOrSecretHashForRedeemingMintedNotes,

// Consume the message from the outbox
registry.getOutbox().consume(
DataStructures.L2ToL1Msg({
sender: DataStructures.L2Actor(l2UniswapAddress, 1),
recipient: DataStructures.L1Actor(address(this), block.chainid),
content: vars.contentHash
})
);

// Perform the swap
ISwapRouter.ExactInputSingleParams memory swapParams;
{
swapParams = ISwapRouter.ExactInputSingleParams({
tokenIn: address(vars.inputAsset),
tokenOut: address(vars.outputAsset),
fee: _uniswapFeeTier,
recipient: address(this),
deadline: block.timestamp,
amountIn: _inAmount,
amountOutMinimum: _amountOutMinimum,
sqrtPriceLimitX96: 0
});
}
// Note, safeApprove was deprecated from Oz
vars.inputAsset.approve(address(ROUTER), _inAmount);
uint256 amountOut = ROUTER.exactInputSingle(swapParams);

// approve the output token portal to take funds from this contract
// Note, safeApprove was deprecated from Oz
vars.outputAsset.approve(address(_outputTokenPortal), amountOut);

// Deposit the output asset to the L2 via its portal
return TokenPortal(_outputTokenPortal).depositToAztecPrivate{value: msg.value}(
amountOut,
_secretHashForRedeemingMintedNotes,
_canceller,
_deadlineForL1ToL2Message,
_secretHashForL1ToL2Message,
_canceller
_secretHashForL1ToL2Message
);
}
// docs:end:solidity_uniswap_swap
}
Loading

0 comments on commit 2ecb9ea

Please sign in to comment.