From 5bdf8bf7e560abda8e258ef3b9e992366c903570 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 30 Nov 2022 14:36:20 -0500 Subject: [PATCH 01/65] address registry and nft vault --- src/bridges/nft-basic/NftVault.sol | 93 +++++++++++ src/bridges/registry/AddressRegistry.sol | 76 +++++++++ src/test/bridges/nft-basic/ExampleE2E.t.sol | 109 +++++++++++++ src/test/bridges/nft-basic/ExampleUnit.t.sol | 119 ++++++++++++++ .../bridges/registry/AddressRegistryE2E.t.sol | 108 +++++++++++++ .../registry/AddressRegistryUnitTest.t.sol | 151 ++++++++++++++++++ 6 files changed, 656 insertions(+) create mode 100644 src/bridges/nft-basic/NftVault.sol create mode 100644 src/bridges/registry/AddressRegistry.sol create mode 100644 src/test/bridges/nft-basic/ExampleE2E.t.sol create mode 100644 src/test/bridges/nft-basic/ExampleUnit.t.sol create mode 100644 src/test/bridges/registry/AddressRegistryE2E.t.sol create mode 100644 src/test/bridges/registry/AddressRegistryUnitTest.t.sol diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol new file mode 100644 index 000000000..78a1b37b2 --- /dev/null +++ b/src/bridges/nft-basic/NftVault.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {IERC721} from "../../../lib/openzeppelin-contracts/contracts/interfaces/IERC721.sol"; +import {AztecTypes} from "../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; +import {ErrorLib} from "../base/ErrorLib.sol"; +import {BridgeBase} from "../base/BridgeBase.sol"; +import {AddressRegistry} from "../registry/AddressRegistry.sol"; + +/** + * @title An example bridge contract. + * @author Aztec Team + * @notice You can use this contract to immediately get back what you've deposited. + * @dev This bridge demonstrates the flow of assets in the convert function. This bridge simply returns what has been + * sent to it. + */ +contract NftVault is BridgeBase { + struct NftAsset { + address collection; + uint256 id; + } + mapping(uint256 => NftAsset) public tokens; + + AddressRegistry public registry = AddressRegistry(address(0x0)); + + constructor(address _rollupProcessor) BridgeBase(_rollupProcessor) {} + + function convert( + AztecTypes.AztecAsset calldata _inputAssetA, + AztecTypes.AztecAsset calldata, + AztecTypes.AztecAsset calldata _outputAssetA, + AztecTypes.AztecAsset calldata, + uint256 _totalInputValue, + uint256 _interactionNonce, + uint64 _auxData, + address + ) + external + payable + override( + // uint64 _auxData, + // address _rollupBeneficiary + BridgeBase + ) + onlyRollup + returns (uint256 outputValueA, uint256, bool) + { + // DEPOSIT + // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum + if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && + _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + ) { + require(_totalInputValue == 1, "send only 1 wei"); + tokens[_interactionNonce] = NftAsset({ + collection: address(0x0), + id: 0 + }); + return (1, 0, false); + } + // WITHDRAW + else if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && + _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + ) { + NftAsset memory token = tokens[_inputAssetA.id]; + require(token.collection != address(0x0), "NFT doesn't exist"); + + address _to = registry.addresses(_auxData); + require(_to != address(0x0), "unregistered withdraw address"); + + IERC721(token.collection).transferFrom(address(this), _to, token.id); + delete tokens[_inputAssetA.id]; + return (0, 0, false); + } + } + + function matchDeposit( + uint256 _virtualAssetId, + address _collection, + address _from, + uint256 _tokenId + ) external { + NftAsset memory asset = tokens[_virtualAssetId]; + require(asset.collection == address(0x0), "Asset registered"); + IERC721(_collection).transferFrom(_from, address(this), _tokenId); + tokens[_virtualAssetId] = NftAsset({ + collection: _collection, + id: _tokenId + }); + } +} diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol new file mode 100644 index 000000000..d92dd64f9 --- /dev/null +++ b/src/bridges/registry/AddressRegistry.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {AztecTypes} from "../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; +import {ErrorLib} from "../base/ErrorLib.sol"; +import {BridgeBase} from "../base/BridgeBase.sol"; + +/** + * @title + * @author + * @notice + * @dev + */ +contract AddressRegistry is BridgeBase { + uint64 public id; + mapping(uint64 => address) public addresses; + uint256 public MAX_INT = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + event AddressRegistered( + uint64 indexed id, + address indexed registeredAddress + ); + + /** + * @notice Set address of rollup processor + * @param _rollupProcessor Address of rollup processor + */ + constructor(address _rollupProcessor) BridgeBase(_rollupProcessor) {} + + function convert( + AztecTypes.AztecAsset calldata _inputAssetA, + AztecTypes.AztecAsset calldata, + AztecTypes.AztecAsset calldata _outputAssetA, + AztecTypes.AztecAsset calldata, + uint256 _totalInputValue, + uint256, + uint64, + address + ) + external + payable + override(BridgeBase) + onlyRollup + returns (uint256 outputValueA, uint256, bool) + { + if ( + _inputAssetA.assetType != AztecTypes.AztecAssetType.NOT_USED || + _inputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL + ) revert ErrorLib.InvalidInputA(); + if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) + revert ErrorLib.InvalidOutputA(); + + // get virtual assets + if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED && + _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + ) { + return (MAX_INT, 0, false); + } + // register address with virtual asset + else if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && + _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + ) { + address toRegister = address(uint160(_totalInputValue)); + addresses[id] = toRegister; + emit AddressRegistered(id, toRegister); + id++; + return (0, 0, false); + } else { + revert(); + } + } +} diff --git a/src/test/bridges/nft-basic/ExampleE2E.t.sol b/src/test/bridges/nft-basic/ExampleE2E.t.sol new file mode 100644 index 000000000..9f64f7f84 --- /dev/null +++ b/src/test/bridges/nft-basic/ExampleE2E.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +// Example-specific imports +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +/** + * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment + * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). + */ +contract ExampleE2ETest is BridgeTestBase { + address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + address private constant BENEFICIARY = address(11); + + // The reference to the example bridge + ExampleBridge internal bridge; + // To store the id of the example bridge after being added + uint256 private id; + + function setUp() public { + // Deploy a new example bridge + bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); + + // Use the label cheatcode to mark the address with "Example Bridge" in the traces + vm.label(address(bridge), "Example Bridge"); + + // Impersonate the multi-sig to add a new bridge + vm.startPrank(MULTI_SIG); + + // List the example-bridge with a gasLimit of 120k + // WARNING: If you set this value too low the interaction will fail for seemingly no reason! + // OTOH if you se it too high bridge users will pay too much + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + + // List USDC with a gasLimit of 100k + // Note: necessary for assets which are not already registered on RollupProcessor + // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get + // addresses of all the listed ERC20 tokens + ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); + + vm.stopPrank(); + + // Fetch the id of the example bridge + id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); + + // Subsidize the bridge when used with USDC and register a beneficiary + AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); + uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); + uint32 gasPerMinute = 200; + SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); + + SUBSIDY.registerBeneficiary(BENEFICIARY); + + // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData + ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); + } + + // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. + function testExampleBridgeE2ETest(uint96 _depositAmount) public { + vm.assume(_depositAmount > 1); + vm.warp(block.timestamp + 1 days); + + // Use the helper function to fetch the support AztecAsset for DAI + AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); + + // Mint the depositAmount of Dai to rollupProcessor + deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); + + // Computes the encoded data for the specific bridge interaction + ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this + + // Check the output values are as expected + assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + + // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) + assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + + // Perform a second rollup with half the deposit, perform similar checks. + uint256 secondDeposit = _depositAmount / 2; + + ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // Check the output values are as expected + assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + + // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) + assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + + assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); + } +} diff --git a/src/test/bridges/nft-basic/ExampleUnit.t.sol b/src/test/bridges/nft-basic/ExampleUnit.t.sol new file mode 100644 index 000000000..0c6aeb464 --- /dev/null +++ b/src/test/bridges/nft-basic/ExampleUnit.t.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +// Example-specific imports +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +// @notice The purpose of this test is to directly test convert functionality of the bridge. +contract ExampleUnitTest is BridgeTestBase { + address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + address private constant BENEFICIARY = address(11); + + address private rollupProcessor; + // The reference to the example bridge + ExampleBridge private bridge; + + // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real + // rollup processor would. + function receiveEthFromBridge(uint256 _interactionNonce) external payable {} + + function setUp() public { + // In unit tests we set address of rollupProcessor to the address of this test contract + rollupProcessor = address(this); + + // Deploy a new example bridge + bridge = new ExampleBridge(rollupProcessor); + + // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) + vm.deal(address(bridge), 0); + vm.deal(BENEFICIARY, 0); + + // Use the label cheatcode to mark the address with "Example Bridge" in the traces + vm.label(address(bridge), "Example Bridge"); + + // Subsidize the bridge when used with Dai and register a beneficiary + AztecTypes.AztecAsset memory daiAsset = ROLLUP_ENCODER.getRealAztecAsset(DAI); + uint256 criteria = bridge.computeCriteria(daiAsset, emptyAsset, daiAsset, emptyAsset, 0); + uint32 gasPerMinute = 200; + SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); + + SUBSIDY.registerBeneficiary(BENEFICIARY); + } + + function testInvalidCaller(address _callerAddress) public { + vm.assume(_callerAddress != rollupProcessor); + // Use HEVM cheatcode to call from a different address than is address(this) + vm.prank(_callerAddress); + vm.expectRevert(ErrorLib.InvalidCaller.selector); + bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); + } + + function testInvalidInputAssetType() public { + vm.expectRevert(ErrorLib.InvalidInputA.selector); + bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); + } + + function testInvalidOutputAssetType() public { + AztecTypes.AztecAsset memory inputAssetA = + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); + vm.expectRevert(ErrorLib.InvalidOutputA.selector); + bridge.convert(inputAssetA, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); + } + + function testExampleBridgeUnitTestFixed() public { + testExampleBridgeUnitTest(10 ether); + } + + // @notice The purpose of this test is to directly test convert functionality of the bridge. + // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. + function testExampleBridgeUnitTest(uint96 _depositAmount) public { + vm.warp(block.timestamp + 1 days); + + // Define input and output assets + AztecTypes.AztecAsset memory inputAssetA = + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); + + AztecTypes.AztecAsset memory outputAssetA = inputAssetA; + + // Rollup processor transfers ERC20 tokens to the bridge before calling convert. Since we are calling + // bridge.convert(...) function directly we have to transfer the funds in the test on our own. In this case + // we'll solve it by directly minting the _depositAmount of Dai to the bridge. + deal(DAI, address(bridge), _depositAmount); + + // Store dai balance before interaction to be able to verify the balance after interaction is correct + uint256 daiBalanceBefore = IERC20(DAI).balanceOf(rollupProcessor); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + inputAssetA, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + outputAssetA, // _outputAssetA - in this example equal to input asset + emptyAsset, // _outputAssetB - not used so can be left empty + _depositAmount, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + BENEFICIARY // _rollupBeneficiary - address, the subsidy will be sent to + ); + + // Now we transfer the funds back from the bridge to the rollup processor + // In this case input asset equals output asset so I only work with the input asset definition + // Basically in all the real world use-cases output assets would differ from input assets + IERC20(inputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA); + + assertEq(outputValueA, _depositAmount, "Output value A doesn't equal deposit amount"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + + uint256 daiBalanceAfter = IERC20(DAI).balanceOf(rollupProcessor); + + assertEq(daiBalanceAfter - daiBalanceBefore, _depositAmount, "Balances must match"); + + SUBSIDY.withdraw(BENEFICIARY); + assertGt(BENEFICIARY.balance, 0, "Subsidy was not claimed"); + } +} diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol new file mode 100644 index 000000000..40e20c0d9 --- /dev/null +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -0,0 +1,108 @@ +// // SPDX-License-Identifier: Apache-2.0 +// // Copyright 2022 Aztec. +// pragma solidity >=0.8.4; + +// import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +// import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; + +// // Example-specific imports +// import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; +// import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +// /** +// * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment +// * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). +// */ +// contract AddressRegistryE2ETest is BridgeTestBase { +// address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; +// address private constant BENEFICIARY = address(11); + +// // The reference to the example bridge +// ExampleBridge internal bridge; +// // To store the id of the example bridge after being added +// uint256 private id; + +// function setUp() public { +// // Deploy a new example bridge +// bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); + +// // Use the label cheatcode to mark the address with "Example Bridge" in the traces +// vm.label(address(bridge), "Example Bridge"); + +// // Impersonate the multi-sig to add a new bridge +// vm.startPrank(MULTI_SIG); + +// // List the example-bridge with a gasLimit of 120k +// // WARNING: If you set this value too low the interaction will fail for seemingly no reason! +// // OTOH if you se it too high bridge users will pay too much +// ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + +// // List USDC with a gasLimit of 100k +// // Note: necessary for assets which are not already registered on RollupProcessor +// // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get +// // addresses of all the listed ERC20 tokens +// ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); + +// vm.stopPrank(); + +// // Fetch the id of the example bridge +// id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); + +// // Subsidize the bridge when used with USDC and register a beneficiary +// AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); +// uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); +// uint32 gasPerMinute = 200; +// SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); + +// SUBSIDY.registerBeneficiary(BENEFICIARY); + +// // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData +// ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); +// } + +// // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. +// function testExampleBridgeE2ETest(uint96 _depositAmount) public { +// vm.assume(_depositAmount > 1); +// vm.warp(block.timestamp + 1 days); + +// // Use the helper function to fetch the support AztecAsset for DAI +// AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); + +// // Mint the depositAmount of Dai to rollupProcessor +// deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); + +// // Computes the encoded data for the specific bridge interaction +// ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); + +// // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. +// (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + +// // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this + +// // Check the output values are as expected +// assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); +// assertEq(outputValueB, 0, "Non-zero outputValueB"); +// assertFalse(isAsync, "Bridge is not synchronous"); + +// // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) +// assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + +// // Perform a second rollup with half the deposit, perform similar checks. +// uint256 secondDeposit = _depositAmount / 2; + +// ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); + +// // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. +// (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + +// // Check the output values are as expected +// assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); +// assertEq(outputValueB, 0, "Non-zero outputValueB"); +// assertFalse(isAsync, "Bridge is not synchronous"); + +// // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) +// assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + +// assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); +// } +// } diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol new file mode 100644 index 000000000..61c05e1e0 --- /dev/null +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; + +// Example-specific imports +import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +// @notice The purpose of this test is to directly test convert functionality of the bridge. +contract AddressRegistryUnitTest is BridgeTestBase { + address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + address private rollupProcessor; + // The reference to the example bridge + AddressRegistry private bridge; + uint256 MAX_INT = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real + // rollup processor would. + function receiveEthFromBridge(uint256 _interactionNonce) external payable {} + + function setUp() public { + // In unit tests we set address of rollupProcessor to the address of this test contract + rollupProcessor = address(this); + + // Deploy a new example bridge + bridge = new AddressRegistry(rollupProcessor); + + // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) + vm.deal(address(bridge), 0); + + // Use the label cheatcode to mark the address with "Example Bridge" in the traces + vm.label(address(bridge), "AddressRegistry Bridge"); + } + + function testInvalidCaller(address _callerAddress) public { + vm.assume(_callerAddress != rollupProcessor); + // Use HEVM cheatcode to call from a different address than is address(this) + vm.prank(_callerAddress); + vm.expectRevert(ErrorLib.InvalidCaller.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidInputAssetType() public { + vm.expectRevert(ErrorLib.InvalidInputA.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidOutputAssetType() public { + AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ + id: 1, + erc20Address: DAI, + assetType: AztecTypes.AztecAssetType.ERC20 + }); + vm.expectRevert(ErrorLib.InvalidOutputA.selector); + bridge.convert( + inputAssetA, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + // @notice The purpose of this test is to directly test convert functionality of the bridge. + function testGetBackMaxVirtualAssets() public { + vm.warp(block.timestamp + 1 days); + + AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + emptyAsset, + emptyAsset, + outputAssetA, + emptyAsset, + 0, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); + + assertEq(outputValueA, MAX_INT, "Output value A doesn't equal MAX_INT"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + } + + function testRegistringAnAddress() public { + vm.warp(block.timestamp + 1 days); + + // Define input and output assets + AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + + uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + inputAssetA, + emptyAsset, + emptyAsset, + emptyAsset, + inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); + + address newlyRegistered = bridge.addresses(0); + + assertEq( + address(inputAmount), + newlyRegistered, + "Address not registered" + ); + assertEq(outputValueA, 0, "Output value is not 0"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + } +} From f0296ef102ab1a8a865ea95ec212d065782b0df3 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Wed, 30 Nov 2022 20:03:06 -0500 Subject: [PATCH 02/65] updates --- src/bridges/nft-basic/NftVault.sol | 2 +- src/bridges/registry/AddressRegistry.sol | 4 +-- .../registry/AddressRegistryUnitTest.t.sol | 25 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 78a1b37b2..69576a2ef 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -44,7 +44,7 @@ contract NftVault is BridgeBase { BridgeBase ) onlyRollup - returns (uint256 outputValueA, uint256, bool) + returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { // DEPOSIT // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index d92dd64f9..2845f7a90 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -46,8 +46,8 @@ contract AddressRegistry is BridgeBase { returns (uint256 outputValueA, uint256, bool) { if ( - _inputAssetA.assetType != AztecTypes.AztecAssetType.NOT_USED || - _inputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH || + _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) revert ErrorLib.InvalidOutputA(); diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 61c05e1e0..da30c182c 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -13,7 +13,6 @@ import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; contract AddressRegistryUnitTest is BridgeTestBase { address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address private rollupProcessor; - // The reference to the example bridge AddressRegistry private bridge; uint256 MAX_INT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; @@ -30,9 +29,9 @@ contract AddressRegistryUnitTest is BridgeTestBase { bridge = new AddressRegistry(rollupProcessor); // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) - vm.deal(address(bridge), 0); + // vm.deal(address(bridge), 0); - // Use the label cheatcode to mark the address with "Example Bridge" in the traces + // Use the label cheatcode to mark the address with "AddressRegistry Bridge" in the traces vm.label(address(bridge), "AddressRegistry Bridge"); } @@ -54,9 +53,15 @@ contract AddressRegistryUnitTest is BridgeTestBase { } function testInvalidInputAssetType() public { + AztecTypes.AztecAsset memory inputAsset = AztecTypes.AztecAsset({ + id: 1, + erc20Address: DAI, + assetType: AztecTypes.AztecAssetType.ERC20 + }); + vm.expectRevert(ErrorLib.InvalidInputA.selector); bridge.convert( - emptyAsset, + inputAsset, emptyAsset, emptyAsset, emptyAsset, @@ -68,16 +73,16 @@ contract AddressRegistryUnitTest is BridgeTestBase { } function testInvalidOutputAssetType() public { - AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ + AztecTypes.AztecAsset memory outputAsset = AztecTypes.AztecAsset({ id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20 }); vm.expectRevert(ErrorLib.InvalidOutputA.selector); bridge.convert( - inputAssetA, emptyAsset, emptyAsset, + outputAsset, emptyAsset, 0, 0, @@ -123,13 +128,19 @@ contract AddressRegistryUnitTest is BridgeTestBase { assetType: AztecTypes.AztecAssetType.VIRTUAL }); + AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge .convert( inputAssetA, emptyAsset, - emptyAsset, + outputAssetA, emptyAsset, inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge 0, // _interactionNonce From 596fe4ab42f6f5fb3d03c7af1ad5ead8855aff19 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 10:14:31 -0500 Subject: [PATCH 03/65] e2e test --- src/bridges/registry/AddressRegistry.sol | 4 +- .../bridges/registry/AddressRegistryE2E.t.sol | 224 +++++++++--------- .../registry/AddressRegistryUnitTest.t.sol | 4 +- 3 files changed, 120 insertions(+), 112 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 2845f7a90..4353801c0 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -15,7 +15,7 @@ import {BridgeBase} from "../base/BridgeBase.sol"; contract AddressRegistry is BridgeBase { uint64 public id; mapping(uint64 => address) public addresses; - uint256 public MAX_INT = + uint256 public maxInt = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; event AddressRegistered( @@ -57,7 +57,7 @@ contract AddressRegistry is BridgeBase { _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - return (MAX_INT, 0, false); + return (maxInt, 0, false); } // register address with virtual asset else if ( diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 40e20c0d9..2b4e3079e 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -1,108 +1,116 @@ -// // SPDX-License-Identifier: Apache-2.0 -// // Copyright 2022 Aztec. -// pragma solidity >=0.8.4; - -// import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -// import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; - -// // Example-specific imports -// import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; -// import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; - -// /** -// * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment -// * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). -// */ -// contract AddressRegistryE2ETest is BridgeTestBase { -// address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; -// address private constant BENEFICIARY = address(11); - -// // The reference to the example bridge -// ExampleBridge internal bridge; -// // To store the id of the example bridge after being added -// uint256 private id; - -// function setUp() public { -// // Deploy a new example bridge -// bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); - -// // Use the label cheatcode to mark the address with "Example Bridge" in the traces -// vm.label(address(bridge), "Example Bridge"); - -// // Impersonate the multi-sig to add a new bridge -// vm.startPrank(MULTI_SIG); - -// // List the example-bridge with a gasLimit of 120k -// // WARNING: If you set this value too low the interaction will fail for seemingly no reason! -// // OTOH if you se it too high bridge users will pay too much -// ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); - -// // List USDC with a gasLimit of 100k -// // Note: necessary for assets which are not already registered on RollupProcessor -// // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get -// // addresses of all the listed ERC20 tokens -// ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); - -// vm.stopPrank(); - -// // Fetch the id of the example bridge -// id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); - -// // Subsidize the bridge when used with USDC and register a beneficiary -// AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); -// uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); -// uint32 gasPerMinute = 200; -// SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); - -// SUBSIDY.registerBeneficiary(BENEFICIARY); - -// // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData -// ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); -// } - -// // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. -// function testExampleBridgeE2ETest(uint96 _depositAmount) public { -// vm.assume(_depositAmount > 1); -// vm.warp(block.timestamp + 1 days); - -// // Use the helper function to fetch the support AztecAsset for DAI -// AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); - -// // Mint the depositAmount of Dai to rollupProcessor -// deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); - -// // Computes the encoded data for the specific bridge interaction -// ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); - -// // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. -// (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - -// // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this - -// // Check the output values are as expected -// assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); -// assertEq(outputValueB, 0, "Non-zero outputValueB"); -// assertFalse(isAsync, "Bridge is not synchronous"); - -// // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) -// assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - -// // Perform a second rollup with half the deposit, perform similar checks. -// uint256 secondDeposit = _depositAmount / 2; - -// ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); - -// // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. -// (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - -// // Check the output values are as expected -// assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); -// assertEq(outputValueB, 0, "Non-zero outputValueB"); -// assertFalse(isAsync, "Bridge is not synchronous"); - -// // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) -// assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - -// assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); -// } -// } +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; + +// Example-specific imports +import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +/** + * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment + * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). + */ +contract AddressRegistryE2ETest is BridgeTestBase { + // address private constant BENEFICIARY = address(11); + + // The reference to the example bridge + AddressRegistry internal bridge; + // To store the id of the example bridge after being added + uint256 private id; + + uint256 public maxInt = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + function setUp() public { + // Deploy a new example bridge + bridge = new AddressRegistry(address(ROLLUP_PROCESSOR)); + + // Use the label cheatcode to mark the address with "Example Bridge" in the traces + vm.label(address(bridge), "Address Registry Bridge"); + + // Impersonate the multi-sig to add a new bridge + vm.startPrank(MULTI_SIG); + + // List the example-bridge with a gasLimit of 120k + // WARNING: If you set this value too low the interaction will fail for seemingly no reason! + // OTOH if you se it too high bridge users will pay too much + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + + vm.stopPrank(); + + // Fetch the id of the example bridge + id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); + } + + // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. + function testAddressRegistryE2ETest(uint96 _depositAmount) public { + vm.assume(_depositAmount > 1); + vm.warp(block.timestamp + 1 days); + + // Define input and output assets + AztecTypes.AztecAsset memory virtualAsset1 = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + + // Computes the encoded data for the specific bridge interaction + ROLLUP_ENCODER.defiInteractionL2( + id, + emptyAsset, + emptyAsset, + virtualAsset1, + emptyAsset, + 0, + 0 + ); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + ( + uint256 outputValueA, + uint256 outputValueB, + bool isAsync + ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // Check the output values are as expected + assertEq( + outputValueA, + maxInt, + "outputValueA doesn't equal maxInt" + ); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + + uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + + ROLLUP_ENCODER.defiInteractionL2( + id, + virtualAsset1, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + inputAmount + ); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER + .processRollupAndGetBridgeResult(); + + uint64 addressId = bridge.id(); + uint64 registeredId = addressId--; + address newlyRegistered = bridge.addresses(registeredId); + + // Check the output values are as expected + assertEq( + inputAmount, + newlyRegistered, + "input amount doesn't equal newly registered address" + ); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + } +} diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index da30c182c..3ed4b95c1 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -14,7 +14,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address private rollupProcessor; AddressRegistry private bridge; - uint256 MAX_INT = + uint256 public maxInt = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real @@ -113,7 +113,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { address(0x0) ); - assertEq(outputValueA, MAX_INT, "Output value A doesn't equal MAX_INT"); + assertEq(outputValueA, maxInt, "Output value A doesn't equal maxInt"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); } From 4dc874c1ac24114f04094380e34be4b178c3def8 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 10:20:24 -0500 Subject: [PATCH 04/65] update max int --- src/bridges/registry/AddressRegistry.sol | 3 +-- src/test/bridges/registry/AddressRegistryE2E.t.sol | 5 ++--- src/test/bridges/registry/AddressRegistryUnitTest.t.sol | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 4353801c0..9dfc3cf33 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -15,8 +15,7 @@ import {BridgeBase} from "../base/BridgeBase.sol"; contract AddressRegistry is BridgeBase { uint64 public id; mapping(uint64 => address) public addresses; - uint256 public maxInt = - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + uint256 public maxInt = type(uint160).max; event AddressRegistered( uint64 indexed id, diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 2b4e3079e..124d989f2 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -21,8 +21,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { // To store the id of the example bridge after being added uint256 private id; - uint256 public maxInt = - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + uint256 public maxInt = type(uint160).max; function setUp() public { // Deploy a new example bridge @@ -106,7 +105,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { // Check the output values are as expected assertEq( - inputAmount, + address(inputAmount), newlyRegistered, "input amount doesn't equal newly registered address" ); diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 3ed4b95c1..e47b2e1d0 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -14,8 +14,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address private rollupProcessor; AddressRegistry private bridge; - uint256 public maxInt = - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + uint256 public maxInt = type(uint160).max; // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real // rollup processor would. From 19f3adaa9f88f08a9c8fdc890fb45ef98bbf31de Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 10:35:46 -0500 Subject: [PATCH 05/65] remove deposit param --- src/test/bridges/registry/AddressRegistryE2E.t.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 124d989f2..831d6936b 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -44,9 +44,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); } - // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. - function testAddressRegistryE2ETest(uint96 _depositAmount) public { - vm.assume(_depositAmount > 1); + function testAddressRegistryE2ETest() public { vm.warp(block.timestamp + 1 days); // Define input and output assets From a370585d9b274e98515e3309bc18baa76be26b59 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 10:39:00 -0500 Subject: [PATCH 06/65] increase gas --- src/test/bridges/registry/AddressRegistryE2E.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 831d6936b..f695bf4e0 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -36,7 +36,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { // List the example-bridge with a gasLimit of 120k // WARNING: If you set this value too low the interaction will fail for seemingly no reason! // OTOH if you se it too high bridge users will pay too much - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 1200000); vm.stopPrank(); From 847cc310c4d58aee0a926739f03417ccd47115b3 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 11:32:14 -0500 Subject: [PATCH 07/65] e2e working --- .../bridges/registry/AddressRegistryE2E.t.sol | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index f695bf4e0..3491d8cb1 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -20,12 +20,22 @@ contract AddressRegistryE2ETest is BridgeTestBase { AddressRegistry internal bridge; // To store the id of the example bridge after being added uint256 private id; - + AztecTypes.AztecAsset private ethAsset; + AztecTypes.AztecAsset private virtualAsset1; uint256 public maxInt = type(uint160).max; + event log(string, uint); + event logAddress(address); function setUp() public { // Deploy a new example bridge bridge = new AddressRegistry(address(ROLLUP_PROCESSOR)); + ethAsset = ROLLUP_ENCODER.getRealAztecAsset(address(0)); + // Define input and output assets + virtualAsset1 = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); // Use the label cheatcode to mark the address with "Example Bridge" in the traces vm.label(address(bridge), "Address Registry Bridge"); @@ -44,27 +54,33 @@ contract AddressRegistryE2ETest is BridgeTestBase { id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); } - function testAddressRegistryE2ETest() public { + function testGetVirtualAssets() public { vm.warp(block.timestamp + 1 days); - // Define input and output assets - AztecTypes.AztecAsset memory virtualAsset1 = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - // Computes the encoded data for the specific bridge interaction + // uint256 bridgeCallData = ROLLUP_ENCODER.defiInteractionL2( id, - emptyAsset, + ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, - 0 + 1 ); + // bytes memory err = abi.encodePacked(ErrorLib.InvalidAuxData.selector); + + // ROLLUP_ENCODER.registerEventToBeChecked( + // bridgeCallData, + // ROLLUP_ENCODER.getNextNonce(), + // 0, + // maxInt, + // 0, + // true, + // err + // ); + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. ( uint256 outputValueA, @@ -73,32 +89,35 @@ contract AddressRegistryE2ETest is BridgeTestBase { ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); // Check the output values are as expected - assertEq( - outputValueA, - maxInt, - "outputValueA doesn't equal maxInt" - ); + assertEq(outputValueA, maxInt, "outputValueA doesn't equal maxInt"); assertEq(outputValueB, 0, "Non-zero outputValueB"); assertFalse(isAsync, "Bridge is not synchronous"); + } - uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + function testRegistration() public { + uint160 inputAmount = uint160( + 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA + ); ROLLUP_ENCODER.defiInteractionL2( id, virtualAsset1, emptyAsset, - emptyAsset, + virtualAsset1, emptyAsset, 0, inputAmount ); // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER - .processRollupAndGetBridgeResult(); + ( + uint256 outputValueA, + uint256 outputValueB, + bool isAsync + ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); uint64 addressId = bridge.id(); - uint64 registeredId = addressId--; + uint64 registeredId = addressId - 1; address newlyRegistered = bridge.addresses(registeredId); // Check the output values are as expected From 52e1a43469d6d40e60913977656080ec0ffada8b Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 11:32:25 -0500 Subject: [PATCH 08/65] add input value --- src/bridges/registry/AddressRegistry.sol | 5 +++-- .../registry/AddressRegistryUnitTest.t.sol | 22 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 9dfc3cf33..450fa6265 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -45,7 +45,7 @@ contract AddressRegistry is BridgeBase { returns (uint256 outputValueA, uint256, bool) { if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH || + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) @@ -53,9 +53,10 @@ contract AddressRegistry is BridgeBase { // get virtual assets if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED && + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { + require(_totalInputValue == 1, "send only 1 wei"); return (maxInt, 0, false); } // register address with virtual asset diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index e47b2e1d0..4b1bd6579 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -15,6 +15,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { address private rollupProcessor; AddressRegistry private bridge; uint256 public maxInt = type(uint160).max; + AztecTypes.AztecAsset private ethAsset; // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real // rollup processor would. @@ -72,6 +73,11 @@ contract AddressRegistryUnitTest is BridgeTestBase { } function testInvalidOutputAssetType() public { + AztecTypes.AztecAsset memory inputAsset = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.ETH + }); AztecTypes.AztecAsset memory outputAsset = AztecTypes.AztecAsset({ id: 1, erc20Address: DAI, @@ -79,7 +85,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { }); vm.expectRevert(ErrorLib.InvalidOutputA.selector); bridge.convert( - emptyAsset, + inputAsset, emptyAsset, outputAsset, emptyAsset, @@ -94,6 +100,12 @@ contract AddressRegistryUnitTest is BridgeTestBase { function testGetBackMaxVirtualAssets() public { vm.warp(block.timestamp + 1 days); + AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.ETH + }); + AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset({ id: 0, erc20Address: address(0), @@ -102,11 +114,11 @@ contract AddressRegistryUnitTest is BridgeTestBase { (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge .convert( - emptyAsset, + inputAssetA, emptyAsset, outputAssetA, emptyAsset, - 0, // _totalInputValue - an amount of input asset A sent to the bridge + 1, // _totalInputValue - an amount of input asset A sent to the bridge 0, // _interactionNonce 0, // _auxData - not used in the example bridge address(0x0) @@ -133,7 +145,9 @@ contract AddressRegistryUnitTest is BridgeTestBase { assetType: AztecTypes.AztecAssetType.VIRTUAL }); - uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + uint160 inputAmount = uint160( + 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA + ); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge .convert( From 63ef608064f418947c5df858b76389175837ece4 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 19:19:03 -0500 Subject: [PATCH 09/65] add registry to constructor --- src/bridges/nft-basic/NftVault.sol | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 69576a2ef..11092d92a 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -22,9 +22,11 @@ contract NftVault is BridgeBase { } mapping(uint256 => NftAsset) public tokens; - AddressRegistry public registry = AddressRegistry(address(0x0)); + AddressRegistry public registry; - constructor(address _rollupProcessor) BridgeBase(_rollupProcessor) {} + constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { + registry = AddressRegistry(_registry); + } function convert( AztecTypes.AztecAsset calldata _inputAssetA, @@ -46,6 +48,12 @@ contract NftVault is BridgeBase { onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { + if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || + _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + ) revert ErrorLib.InvalidInputA(); + if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) + revert ErrorLib.InvalidOutputA(); // DEPOSIT // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum if ( @@ -70,7 +78,11 @@ contract NftVault is BridgeBase { address _to = registry.addresses(_auxData); require(_to != address(0x0), "unregistered withdraw address"); - IERC721(token.collection).transferFrom(address(this), _to, token.id); + IERC721(token.collection).transferFrom( + address(this), + _to, + token.id + ); delete tokens[_inputAssetA.id]; return (0, 0, false); } From 1aa9eb0d8169224fef99fc560b058054768090d1 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 19:19:09 -0500 Subject: [PATCH 10/65] del --- src/test/bridges/nft-basic/ExampleE2E.t.sol | 109 ----------------- src/test/bridges/nft-basic/ExampleUnit.t.sol | 119 ------------------- 2 files changed, 228 deletions(-) delete mode 100644 src/test/bridges/nft-basic/ExampleE2E.t.sol delete mode 100644 src/test/bridges/nft-basic/ExampleUnit.t.sol diff --git a/src/test/bridges/nft-basic/ExampleE2E.t.sol b/src/test/bridges/nft-basic/ExampleE2E.t.sol deleted file mode 100644 index 9f64f7f84..000000000 --- a/src/test/bridges/nft-basic/ExampleE2E.t.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec. -pragma solidity >=0.8.4; - -import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; - -// Example-specific imports -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; -import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; - -/** - * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment - * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). - */ -contract ExampleE2ETest is BridgeTestBase { - address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - address private constant BENEFICIARY = address(11); - - // The reference to the example bridge - ExampleBridge internal bridge; - // To store the id of the example bridge after being added - uint256 private id; - - function setUp() public { - // Deploy a new example bridge - bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); - - // Use the label cheatcode to mark the address with "Example Bridge" in the traces - vm.label(address(bridge), "Example Bridge"); - - // Impersonate the multi-sig to add a new bridge - vm.startPrank(MULTI_SIG); - - // List the example-bridge with a gasLimit of 120k - // WARNING: If you set this value too low the interaction will fail for seemingly no reason! - // OTOH if you se it too high bridge users will pay too much - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); - - // List USDC with a gasLimit of 100k - // Note: necessary for assets which are not already registered on RollupProcessor - // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get - // addresses of all the listed ERC20 tokens - ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); - - vm.stopPrank(); - - // Fetch the id of the example bridge - id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); - - // Subsidize the bridge when used with USDC and register a beneficiary - AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); - uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); - uint32 gasPerMinute = 200; - SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); - - SUBSIDY.registerBeneficiary(BENEFICIARY); - - // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData - ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); - } - - // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. - function testExampleBridgeE2ETest(uint96 _depositAmount) public { - vm.assume(_depositAmount > 1); - vm.warp(block.timestamp + 1 days); - - // Use the helper function to fetch the support AztecAsset for DAI - AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); - - // Mint the depositAmount of Dai to rollupProcessor - deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); - - // Computes the encoded data for the specific bridge interaction - ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); - - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - - // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this - - // Check the output values are as expected - assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); - assertEq(outputValueB, 0, "Non-zero outputValueB"); - assertFalse(isAsync, "Bridge is not synchronous"); - - // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) - assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - - // Perform a second rollup with half the deposit, perform similar checks. - uint256 secondDeposit = _depositAmount / 2; - - ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); - - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - - // Check the output values are as expected - assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); - assertEq(outputValueB, 0, "Non-zero outputValueB"); - assertFalse(isAsync, "Bridge is not synchronous"); - - // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) - assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - - assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); - } -} diff --git a/src/test/bridges/nft-basic/ExampleUnit.t.sol b/src/test/bridges/nft-basic/ExampleUnit.t.sol deleted file mode 100644 index 0c6aeb464..000000000 --- a/src/test/bridges/nft-basic/ExampleUnit.t.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec. -pragma solidity >=0.8.4; - -import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; - -// Example-specific imports -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; -import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; - -// @notice The purpose of this test is to directly test convert functionality of the bridge. -contract ExampleUnitTest is BridgeTestBase { - address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address private constant BENEFICIARY = address(11); - - address private rollupProcessor; - // The reference to the example bridge - ExampleBridge private bridge; - - // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real - // rollup processor would. - function receiveEthFromBridge(uint256 _interactionNonce) external payable {} - - function setUp() public { - // In unit tests we set address of rollupProcessor to the address of this test contract - rollupProcessor = address(this); - - // Deploy a new example bridge - bridge = new ExampleBridge(rollupProcessor); - - // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) - vm.deal(address(bridge), 0); - vm.deal(BENEFICIARY, 0); - - // Use the label cheatcode to mark the address with "Example Bridge" in the traces - vm.label(address(bridge), "Example Bridge"); - - // Subsidize the bridge when used with Dai and register a beneficiary - AztecTypes.AztecAsset memory daiAsset = ROLLUP_ENCODER.getRealAztecAsset(DAI); - uint256 criteria = bridge.computeCriteria(daiAsset, emptyAsset, daiAsset, emptyAsset, 0); - uint32 gasPerMinute = 200; - SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); - - SUBSIDY.registerBeneficiary(BENEFICIARY); - } - - function testInvalidCaller(address _callerAddress) public { - vm.assume(_callerAddress != rollupProcessor); - // Use HEVM cheatcode to call from a different address than is address(this) - vm.prank(_callerAddress); - vm.expectRevert(ErrorLib.InvalidCaller.selector); - bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); - } - - function testInvalidInputAssetType() public { - vm.expectRevert(ErrorLib.InvalidInputA.selector); - bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); - } - - function testInvalidOutputAssetType() public { - AztecTypes.AztecAsset memory inputAssetA = - AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); - vm.expectRevert(ErrorLib.InvalidOutputA.selector); - bridge.convert(inputAssetA, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); - } - - function testExampleBridgeUnitTestFixed() public { - testExampleBridgeUnitTest(10 ether); - } - - // @notice The purpose of this test is to directly test convert functionality of the bridge. - // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. - function testExampleBridgeUnitTest(uint96 _depositAmount) public { - vm.warp(block.timestamp + 1 days); - - // Define input and output assets - AztecTypes.AztecAsset memory inputAssetA = - AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); - - AztecTypes.AztecAsset memory outputAssetA = inputAssetA; - - // Rollup processor transfers ERC20 tokens to the bridge before calling convert. Since we are calling - // bridge.convert(...) function directly we have to transfer the funds in the test on our own. In this case - // we'll solve it by directly minting the _depositAmount of Dai to the bridge. - deal(DAI, address(bridge), _depositAmount); - - // Store dai balance before interaction to be able to verify the balance after interaction is correct - uint256 daiBalanceBefore = IERC20(DAI).balanceOf(rollupProcessor); - - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - inputAssetA, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty - outputAssetA, // _outputAssetA - in this example equal to input asset - emptyAsset, // _outputAssetB - not used so can be left empty - _depositAmount, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - BENEFICIARY // _rollupBeneficiary - address, the subsidy will be sent to - ); - - // Now we transfer the funds back from the bridge to the rollup processor - // In this case input asset equals output asset so I only work with the input asset definition - // Basically in all the real world use-cases output assets would differ from input assets - IERC20(inputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA); - - assertEq(outputValueA, _depositAmount, "Output value A doesn't equal deposit amount"); - assertEq(outputValueB, 0, "Output value B is not 0"); - assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - - uint256 daiBalanceAfter = IERC20(DAI).balanceOf(rollupProcessor); - - assertEq(daiBalanceAfter - daiBalanceBefore, _depositAmount, "Balances must match"); - - SUBSIDY.withdraw(BENEFICIARY); - assertGt(BENEFICIARY.balance, 0, "Subsidy was not claimed"); - } -} From 869e81abd42656950794f39f39526e3b28aba746 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 19:19:21 -0500 Subject: [PATCH 11/65] rename --- src/test/bridges/nft-basic/NftVaultE2E.t.sol | 109 +++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/test/bridges/nft-basic/NftVaultE2E.t.sol diff --git a/src/test/bridges/nft-basic/NftVaultE2E.t.sol b/src/test/bridges/nft-basic/NftVaultE2E.t.sol new file mode 100644 index 000000000..9f64f7f84 --- /dev/null +++ b/src/test/bridges/nft-basic/NftVaultE2E.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +// Example-specific imports +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; + +/** + * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment + * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). + */ +contract ExampleE2ETest is BridgeTestBase { + address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + address private constant BENEFICIARY = address(11); + + // The reference to the example bridge + ExampleBridge internal bridge; + // To store the id of the example bridge after being added + uint256 private id; + + function setUp() public { + // Deploy a new example bridge + bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); + + // Use the label cheatcode to mark the address with "Example Bridge" in the traces + vm.label(address(bridge), "Example Bridge"); + + // Impersonate the multi-sig to add a new bridge + vm.startPrank(MULTI_SIG); + + // List the example-bridge with a gasLimit of 120k + // WARNING: If you set this value too low the interaction will fail for seemingly no reason! + // OTOH if you se it too high bridge users will pay too much + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + + // List USDC with a gasLimit of 100k + // Note: necessary for assets which are not already registered on RollupProcessor + // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get + // addresses of all the listed ERC20 tokens + ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); + + vm.stopPrank(); + + // Fetch the id of the example bridge + id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); + + // Subsidize the bridge when used with USDC and register a beneficiary + AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); + uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); + uint32 gasPerMinute = 200; + SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); + + SUBSIDY.registerBeneficiary(BENEFICIARY); + + // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData + ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); + } + + // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. + function testExampleBridgeE2ETest(uint96 _depositAmount) public { + vm.assume(_depositAmount > 1); + vm.warp(block.timestamp + 1 days); + + // Use the helper function to fetch the support AztecAsset for DAI + AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); + + // Mint the depositAmount of Dai to rollupProcessor + deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); + + // Computes the encoded data for the specific bridge interaction + ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this + + // Check the output values are as expected + assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + + // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) + assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + + // Perform a second rollup with half the deposit, perform similar checks. + uint256 secondDeposit = _depositAmount / 2; + + ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); + + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. + (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // Check the output values are as expected + assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); + assertEq(outputValueB, 0, "Non-zero outputValueB"); + assertFalse(isAsync, "Bridge is not synchronous"); + + // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) + assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); + + assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); + } +} From eafca9e9cfcd4cae7fb50ac473a0bd3796738600 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 19:19:35 -0500 Subject: [PATCH 12/65] deposit + withdraw --- src/test/bridges/nft-basic/NftVaultUnit.t.sol | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 src/test/bridges/nft-basic/NftVaultUnit.t.sol diff --git a/src/test/bridges/nft-basic/NftVaultUnit.t.sol b/src/test/bridges/nft-basic/NftVaultUnit.t.sol new file mode 100644 index 000000000..608e46d44 --- /dev/null +++ b/src/test/bridges/nft-basic/NftVaultUnit.t.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +// Example-specific imports +import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; +import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; +import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; + +// @notice The purpose of this test is to directly test convert functionality of the bridge. +contract NftVaultBasicUnitTest is BridgeTestBase { + struct NftAsset { + address collection; + uint256 id; + } + AztecTypes.AztecAsset private ethAsset = + AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.ETH + }); + AztecTypes.AztecAsset private virtualAsset1 = + AztecTypes.AztecAsset({ + id: 1, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + AztecTypes.AztecAsset private virtualAsset100 = + AztecTypes.AztecAsset({ + id: 100, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + address private rollupProcessor; + // The reference to the example bridge + NftVault private bridge; + ERC721PresetMinterPauserAutoId private nftContract; + uint256 private tokenToDeposit = 1; + AddressRegistry private registry; + address private registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + + event log(string, address); + + // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real + // rollup processor would. + function receiveEthFromBridge(uint256 _interactionNonce) external payable {} + + function setUp() public { + // In unit tests we set address of rollupProcessor to the address of this test contract + rollupProcessor = address(this); + // deploy address registry + registry = new AddressRegistry(rollupProcessor); + // Deploy a new nft vault bridge + bridge = new NftVault(rollupProcessor, address(registry)); + // deploy new nft contract + nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + + nftContract.approve(address(bridge), 0); + nftContract.approve(address(bridge), 1); + nftContract.approve(address(bridge), 2); + + // get virtual assets + registry.convert( + ethAsset, + emptyAsset, + virtualAsset1, + emptyAsset, + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); + uint256 inputAmount = uint160(address(registeredAddress)); + // register an address + registry.convert( + virtualAsset1, + emptyAsset, + virtualAsset1, + emptyAsset, + inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); + + // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) + vm.deal(address(bridge), 0); + + vm.label(address(bridge), "Basic NFT Vault Bridge"); + } + + function testInvalidCaller(address _callerAddress) public { + vm.assume(_callerAddress != rollupProcessor); + // Use HEVM cheatcode to call from a different address than is address(this) + vm.prank(_callerAddress); + vm.expectRevert(ErrorLib.InvalidCaller.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidInputAssetType() public { + vm.expectRevert(ErrorLib.InvalidInputA.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidOutputAssetType() public { + vm.expectRevert(ErrorLib.InvalidOutputA.selector); + bridge.convert( + ethAsset, + emptyAsset, + ethAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + // @notice The purpose of this test is to directly test convert functionality of the bridge. + // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. + function testGetVirtualAssetUnitTest() public { + vm.warp(block.timestamp + 1 days); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + ethAsset, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _outputAssetA - in this example equal to input asset + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0) // _rollupBeneficiary - address, the subsidy will be sent to + ); + + assertEq(outputValueA, 1, "Output value A doesn't equal 1"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + } + + function testDepositandWithdraw() public { + vm.warp(block.timestamp + 1 days); + + address collection = address(nftContract); + address from = address(this); + + bridge.matchDeposit(virtualAsset100.id, collection, from, tokenToDeposit); + + (address returnedCollection, uint256 returnedId) = bridge.tokens( + virtualAsset100.id + ); + + assertEq(returnedId, tokenToDeposit, "nft token id does not match input"); + assertEq( + returnedCollection, + collection, + "collection data does not match" + ); + + uint64 auxData = registry.id() - 1; + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + virtualAsset100, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _outputAssetA - in this example equal to input asset + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + auxData, // _auxData - not used in the example bridge + address(0) // _rollupBeneficiary - address, the subsidy will be sent to + ); + + address owner = nftContract.ownerOf(tokenToDeposit); + + assertEq(registeredAddress, owner, "registered address is not the owner"); + assertEq(outputValueA, 0, "Output value A is not 0"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + } +} From 86e68f769c9a7ae66333d0ec4b81b5699347773e Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 1 Dec 2022 19:19:50 -0500 Subject: [PATCH 13/65] add 0 output check --- src/test/bridges/registry/AddressRegistryE2E.t.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 3491d8cb1..d3d2cf92f 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -126,6 +126,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { newlyRegistered, "input amount doesn't equal newly registered address" ); + assertEq(outputValueA, 0, "Non-zero outputValueA"); assertEq(outputValueB, 0, "Non-zero outputValueB"); assertFalse(isAsync, "Bridge is not synchronous"); } From 202c05eea873a58fe8b12bc12b1d2326dd5f577a Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 16:16:02 -0500 Subject: [PATCH 14/65] update comments --- src/bridges/nft-basic/NftVault.sol | 29 ++++++++++++++---------- src/bridges/registry/AddressRegistry.sol | 10 ++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 11092d92a..f8c7153c0 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -9,11 +9,10 @@ import {BridgeBase} from "../base/BridgeBase.sol"; import {AddressRegistry} from "../registry/AddressRegistry.sol"; /** - * @title An example bridge contract. + * @title Basic NFT Vault for Aztec. * @author Aztec Team - * @notice You can use this contract to immediately get back what you've deposited. - * @dev This bridge demonstrates the flow of assets in the convert function. This bridge simply returns what has been - * sent to it. + * @notice You can use this contract to hold your NFTs on Aztec. Whoever holds the corresponding virutal asset note can withdraw the NFT. + * @dev This bridge demonstrates basic functionality for an NFT bridge. This may be extended to support more features. */ contract NftVault is BridgeBase { struct NftAsset { @@ -24,7 +23,10 @@ contract NftVault is BridgeBase { AddressRegistry public registry; - constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { + constructor( + address _rollupProcessor, + address _registry + ) BridgeBase(_rollupProcessor) { registry = AddressRegistry(_registry); } @@ -52,8 +54,10 @@ contract NftVault is BridgeBase { _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); - if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) - revert ErrorLib.InvalidOutputA(); + if ( + _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || + _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + ) revert ErrorLib.InvalidOutputA(); // DEPOSIT // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum if ( @@ -61,16 +65,16 @@ contract NftVault is BridgeBase { _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { require(_totalInputValue == 1, "send only 1 wei"); - tokens[_interactionNonce] = NftAsset({ - collection: address(0x0), - id: 0 - }); + // tokens[_interactionNonce] = NftAsset({ + // collection: address(0x0), + // id: 0 + // }); return (1, 0, false); } // WITHDRAW else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && - _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { NftAsset memory token = tokens[_inputAssetA.id]; require(token.collection != address(0x0), "NFT doesn't exist"); @@ -88,6 +92,7 @@ contract NftVault is BridgeBase { } } + // user must approve their NFT to be transferred by this contract before calling this function function matchDeposit( uint256 _virtualAssetId, address _collection, diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 450fa6265..e179d14a3 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -7,12 +7,14 @@ import {ErrorLib} from "../base/ErrorLib.sol"; import {BridgeBase} from "../base/BridgeBase.sol"; /** - * @title - * @author - * @notice - * @dev + * @title Aztec Address Registry. + * @author Aztec Team + * @notice This contract can be used to anonymously register an ethereum address with an id. + * This is useful for reducing the amount of data required to pass an ethereum address through auxData. + * @dev Use this contract to lookup ethereum addresses by id. */ contract AddressRegistry is BridgeBase { + uint64 public id; mapping(uint64 => address) public addresses; uint256 public maxInt = type(uint160).max; From d0668a699d9d2480b2fe9b013392309ca8bdb2c5 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 16:16:15 -0500 Subject: [PATCH 15/65] add tests --- .../bridges/nft-basic/NftVaultBasicE2E.t.sol | 188 +++++++++++ .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 297 ++++++++++++++++++ 2 files changed, 485 insertions(+) create mode 100644 src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol create mode 100644 src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol new file mode 100644 index 000000000..f57558014 --- /dev/null +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; + +// Example-specific imports +import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; +import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; +import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; + +/** + * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment + * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). + */ +contract NftVaultBasicE2ETest is BridgeTestBase { + NftVault internal bridge; + AddressRegistry private registry; + ERC721PresetMinterPauserAutoId private nftContract; + + // To store the id of the bridge after being added + uint256 private id; + uint256 private registryBridgeId; + uint256 private tokenIdToDeposit = 1; + address private constant registeredAddress = + 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + AztecTypes.AztecAsset private ethAsset; + AztecTypes.AztecAsset private virtualAsset1 = + AztecTypes.AztecAsset({ + id: 1, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + AztecTypes.AztecAsset private virtualAsset100 = + AztecTypes.AztecAsset({ + id: 100, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + AztecTypes.AztecAsset private erc20InputAsset = + AztecTypes.AztecAsset({ + id: 1, + erc20Address: DAI, + assetType: AztecTypes.AztecAssetType.ERC20 + }); + + function setUp() public { + // deploy address registry + registry = new AddressRegistry(address(ROLLUP_PROCESSOR)); + // Deploy a new nft vault bridge + bridge = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); + nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + + nftContract.approve(address(bridge), 0); + nftContract.approve(address(bridge), 1); + nftContract.approve(address(bridge), 2); + + ethAsset = ROLLUP_ENCODER.getRealAztecAsset(address(0)); + + vm.label(address(registry), "AddressRegistry Bridge"); + vm.label(address(bridge), "NftVault Bridge"); + + // Impersonate the multi-sig to add a new bridge + vm.startPrank(MULTI_SIG); + + // List the example-bridge with a gasLimit of 120k + // WARNING: If you set this value too low the interaction will fail for seemingly no reason! + // OTOH if you se it too high bridge users will pay too much + ROLLUP_PROCESSOR.setSupportedBridge(address(registry), 120000); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + + vm.stopPrank(); + + // Fetch the id of the bridges + registryBridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 1; + id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); + + // get virutal assets to register an address + ROLLUP_ENCODER.defiInteractionL2( + registryBridgeId, + ethAsset, + emptyAsset, + virtualAsset1, + emptyAsset, + 0, + 1 + ); + ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // register an address + uint160 inputAmount = uint160(registeredAddress); + ROLLUP_ENCODER.defiInteractionL2( + registryBridgeId, + virtualAsset1, + emptyAsset, + virtualAsset1, + emptyAsset, + 0, + inputAmount + ); + ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + } + + function testDeposit() public { + // get virtual asset before deposit + ROLLUP_ENCODER.defiInteractionL2( + id, + ethAsset, + emptyAsset, + virtualAsset100, + emptyAsset, + 0, + 1 + ); + + ( + uint256 outputValueA, + uint256 outputValueB, + bool isAsync + ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + assertEq(outputValueA, 1, "Output value A doesn't equal 1"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + + // match deposit + address collection = address(nftContract); + address from = address(this); + bridge.matchDeposit( + virtualAsset100.id, + collection, + from, + tokenIdToDeposit + ); + (address returnedCollection, uint256 returnedId) = bridge.tokens( + virtualAsset100.id + ); + assertEq( + returnedId, + tokenIdToDeposit, + "nft token id does not match input" + ); + assertEq( + returnedCollection, + collection, + "collection data does not match" + ); + } + + function testWithdraw() public { + testDeposit(); + uint64 auxData = registry.id() - 1; + ROLLUP_ENCODER.defiInteractionL2( + id, + virtualAsset100, + emptyAsset, + ethAsset, + emptyAsset, + auxData, + 1 + ); + + ( + uint256 outputValueA, + uint256 outputValueB, + bool isAsync + ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + address owner = nftContract.ownerOf(tokenIdToDeposit); + assertEq( + registeredAddress, + owner, + "registered address is not the owner" + ); + assertEq(outputValueA, 0, "Output value A is not 0"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + + (address _a, uint256 _id) = bridge.tokens(virtualAsset100.id); + assertEq(_a, address(0), "collection address is not 0"); + assertEq(_id, 0, "token id is not 0"); + } +} diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol new file mode 100644 index 000000000..1602b25fa --- /dev/null +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +// Example-specific imports +import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; +import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; +import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; +import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; + +// @notice The purpose of this test is to directly test convert functionality of the bridge. +contract NftVaultBasicUnitTest is BridgeTestBase { + struct NftAsset { + address collection; + uint256 id; + } + + address private rollupProcessor; + // The reference to the example bridge + NftVault private bridge; + ERC721PresetMinterPauserAutoId private nftContract; + uint256 private tokenIdToDeposit = 1; + AddressRegistry private registry; + address private constant registeredAddress = + 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; + + AztecTypes.AztecAsset private ethAsset = + AztecTypes.AztecAsset({ + id: 0, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.ETH + }); + AztecTypes.AztecAsset private virtualAsset1 = + AztecTypes.AztecAsset({ + id: 1, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + AztecTypes.AztecAsset private virtualAsset100 = + AztecTypes.AztecAsset({ + id: 100, + erc20Address: address(0), + assetType: AztecTypes.AztecAssetType.VIRTUAL + }); + AztecTypes.AztecAsset private erc20InputAsset = + AztecTypes.AztecAsset({ + id: 1, + erc20Address: DAI, + assetType: AztecTypes.AztecAssetType.ERC20 + }); + + event log(string, address); + + // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real + // rollup processor would. + function receiveEthFromBridge(uint256 _interactionNonce) external payable {} + + function setUp() public { + // In unit tests we set address of rollupProcessor to the address of this test contract + rollupProcessor = address(this); + // deploy address registry + registry = new AddressRegistry(rollupProcessor); + // Deploy a new nft vault bridge + bridge = new NftVault(rollupProcessor, address(registry)); + // deploy new nft contract + nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + nftContract.mint(address(this)); + + nftContract.approve(address(bridge), 0); + nftContract.approve(address(bridge), 1); + nftContract.approve(address(bridge), 2); + + // get virtual assets + registry.convert( + ethAsset, + emptyAsset, + virtualAsset1, + emptyAsset, + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used + address(0x0) + ); + uint256 inputAmount = uint160(address(registeredAddress)); + // register an address + registry.convert( + virtualAsset1, + emptyAsset, + virtualAsset1, + emptyAsset, + inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); + + // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) + vm.deal(address(bridge), 0); + + vm.label(address(bridge), "Basic NFT Vault Bridge"); + } + + function testInvalidCaller(address _callerAddress) public { + vm.assume(_callerAddress != rollupProcessor); + // Use HEVM cheatcode to call from a different address than is address(this) + vm.prank(_callerAddress); + vm.expectRevert(ErrorLib.InvalidCaller.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidInputAssetType() public { + vm.expectRevert(ErrorLib.InvalidInputA.selector); + bridge.convert( + emptyAsset, + emptyAsset, + emptyAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + function testInvalidOutputAssetType() public { + vm.expectRevert(ErrorLib.InvalidOutputA.selector); + bridge.convert( + ethAsset, + emptyAsset, + erc20InputAsset, + emptyAsset, + 0, + 0, + 0, + address(0) + ); + } + + // @notice The purpose of this test is to directly test convert functionality of the bridge. + function testGetVirtualAssetUnitTest() public { + vm.warp(block.timestamp + 1 days); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + ethAsset, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData + address(0) // _rollupBeneficiary - address, the subsidy will be sent to + ); + + assertEq(outputValueA, 1, "Output value A doesn't equal 1"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + } + + function testGetVirtualAssetShouldFail() public { + vm.warp(block.timestamp + 1 days); + + vm.expectRevert(); + // should fail because sending more than 1 wei + bridge.convert( + ethAsset, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 2, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in this call + address(0) // _rollupBeneficiary - address, the subsidy will be sent to + ); + } + + function testDeposit() public { + vm.warp(block.timestamp + 1 days); + + address collection = address(nftContract); + address from = address(this); + bridge.matchDeposit( + virtualAsset100.id, + collection, + from, + tokenIdToDeposit + ); + (address returnedCollection, uint256 returnedId) = bridge.tokens( + virtualAsset100.id + ); + assertEq( + returnedId, + tokenIdToDeposit, + "nft token id does not match input" + ); + assertEq( + returnedCollection, + collection, + "collection data does not match" + ); + } + + function testDepositFailWithDuplicateNft() public { + testDeposit(); + vm.warp(block.timestamp + 1 days); + + address collection = address(nftContract); + address from = address(this); + + vm.expectRevert(); + // should fail because an NFT with this id has already been deposited + bridge.matchDeposit( + virtualAsset100.id, + collection, + from, + tokenIdToDeposit + ); + } + + function testWithdraw() public { + testDeposit(); + uint64 auxData = registry.id() - 1; + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge + .convert( + virtualAsset100, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + auxData, // _auxData - the id of the eth address to withdraw to from the registry + address(0) + ); + address owner = nftContract.ownerOf(tokenIdToDeposit); + assertEq( + registeredAddress, + owner, + "registered address is not the owner" + ); + assertEq(outputValueA, 0, "Output value A is not 0"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + + (address _a, uint256 _id) = bridge.tokens(virtualAsset100.id); + assertEq(_a, address(0), "collection address is not 0"); + assertEq(_id, 0, "token id is not 0"); + } + + function testWithdrawUnregisteredNft() public { + testDeposit(); + uint64 auxData = registry.id() - 1; + vm.expectRevert(); + // should fail because no NFT has been registered with this virtual asset + bridge.convert( + virtualAsset1, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + auxData, + address(0) + ); + } + + function testWithdrawUnregisteredWithdrawAddress() public { + testDeposit(); + uint64 auxData = 1000; + vm.expectRevert(); + // should fail because no withdraw address has been registered with this id + bridge.convert( + virtualAsset1, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + auxData, + address(0) + ); + } +} From 493646148c683b2ce9c7913b92d4efc8c55208b5 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 16:16:21 -0500 Subject: [PATCH 16/65] del --- src/test/bridges/nft-basic/NftVaultE2E.t.sol | 109 --------- src/test/bridges/nft-basic/NftVaultUnit.t.sol | 207 ------------------ 2 files changed, 316 deletions(-) delete mode 100644 src/test/bridges/nft-basic/NftVaultE2E.t.sol delete mode 100644 src/test/bridges/nft-basic/NftVaultUnit.t.sol diff --git a/src/test/bridges/nft-basic/NftVaultE2E.t.sol b/src/test/bridges/nft-basic/NftVaultE2E.t.sol deleted file mode 100644 index 9f64f7f84..000000000 --- a/src/test/bridges/nft-basic/NftVaultE2E.t.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec. -pragma solidity >=0.8.4; - -import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; - -// Example-specific imports -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ExampleBridge} from "../../../bridges/example/ExampleBridge.sol"; -import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; - -/** - * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment - * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). - */ -contract ExampleE2ETest is BridgeTestBase { - address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; - address private constant BENEFICIARY = address(11); - - // The reference to the example bridge - ExampleBridge internal bridge; - // To store the id of the example bridge after being added - uint256 private id; - - function setUp() public { - // Deploy a new example bridge - bridge = new ExampleBridge(address(ROLLUP_PROCESSOR)); - - // Use the label cheatcode to mark the address with "Example Bridge" in the traces - vm.label(address(bridge), "Example Bridge"); - - // Impersonate the multi-sig to add a new bridge - vm.startPrank(MULTI_SIG); - - // List the example-bridge with a gasLimit of 120k - // WARNING: If you set this value too low the interaction will fail for seemingly no reason! - // OTOH if you se it too high bridge users will pay too much - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); - - // List USDC with a gasLimit of 100k - // Note: necessary for assets which are not already registered on RollupProcessor - // Call https://etherscan.io/address/0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455#readProxyContract#F25 to get - // addresses of all the listed ERC20 tokens - ROLLUP_PROCESSOR.setSupportedAsset(USDC, 100000); - - vm.stopPrank(); - - // Fetch the id of the example bridge - id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); - - // Subsidize the bridge when used with USDC and register a beneficiary - AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(USDC); - uint256 criteria = bridge.computeCriteria(usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0); - uint32 gasPerMinute = 200; - SUBSIDY.subsidize{value: 1 ether}(address(bridge), criteria, gasPerMinute); - - SUBSIDY.registerBeneficiary(BENEFICIARY); - - // Set the rollupBeneficiary on BridgeTestBase so that it gets included in the proofData - ROLLUP_ENCODER.setRollupBeneficiary(BENEFICIARY); - } - - // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. - function testExampleBridgeE2ETest(uint96 _depositAmount) public { - vm.assume(_depositAmount > 1); - vm.warp(block.timestamp + 1 days); - - // Use the helper function to fetch the support AztecAsset for DAI - AztecTypes.AztecAsset memory usdcAsset = ROLLUP_ENCODER.getRealAztecAsset(address(USDC)); - - // Mint the depositAmount of Dai to rollupProcessor - deal(USDC, address(ROLLUP_PROCESSOR), _depositAmount); - - // Computes the encoded data for the specific bridge interaction - ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, _depositAmount); - - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - - // Note: Unlike in unit tests there is no need to manually transfer the tokens - RollupProcessor does this - - // Check the output values are as expected - assertEq(outputValueA, _depositAmount, "outputValueA doesn't equal deposit"); - assertEq(outputValueB, 0, "Non-zero outputValueB"); - assertFalse(isAsync, "Bridge is not synchronous"); - - // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) - assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - - // Perform a second rollup with half the deposit, perform similar checks. - uint256 secondDeposit = _depositAmount / 2; - - ROLLUP_ENCODER.defiInteractionL2(id, usdcAsset, emptyAsset, usdcAsset, emptyAsset, 0, secondDeposit); - - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - (outputValueA, outputValueB, isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - - // Check the output values are as expected - assertEq(outputValueA, secondDeposit, "outputValueA doesn't equal second deposit"); - assertEq(outputValueB, 0, "Non-zero outputValueB"); - assertFalse(isAsync, "Bridge is not synchronous"); - - // Check that the balance of the rollup is same as before interaction (bridge just sends funds back) - assertEq(_depositAmount, IERC20(USDC).balanceOf(address(ROLLUP_PROCESSOR)), "Balances must match"); - - assertGt(SUBSIDY.claimableAmount(BENEFICIARY), 0, "Claimable was not updated"); - } -} diff --git a/src/test/bridges/nft-basic/NftVaultUnit.t.sol b/src/test/bridges/nft-basic/NftVaultUnit.t.sol deleted file mode 100644 index 608e46d44..000000000 --- a/src/test/bridges/nft-basic/NftVaultUnit.t.sol +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec. -pragma solidity >=0.8.4; - -import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; - -// Example-specific imports -import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; -import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; -import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; -import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; - -// @notice The purpose of this test is to directly test convert functionality of the bridge. -contract NftVaultBasicUnitTest is BridgeTestBase { - struct NftAsset { - address collection; - uint256 id; - } - AztecTypes.AztecAsset private ethAsset = - AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.ETH - }); - AztecTypes.AztecAsset private virtualAsset1 = - AztecTypes.AztecAsset({ - id: 1, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - AztecTypes.AztecAsset private virtualAsset100 = - AztecTypes.AztecAsset({ - id: 100, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address private rollupProcessor; - // The reference to the example bridge - NftVault private bridge; - ERC721PresetMinterPauserAutoId private nftContract; - uint256 private tokenToDeposit = 1; - AddressRegistry private registry; - address private registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; - - event log(string, address); - - // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real - // rollup processor would. - function receiveEthFromBridge(uint256 _interactionNonce) external payable {} - - function setUp() public { - // In unit tests we set address of rollupProcessor to the address of this test contract - rollupProcessor = address(this); - // deploy address registry - registry = new AddressRegistry(rollupProcessor); - // Deploy a new nft vault bridge - bridge = new NftVault(rollupProcessor, address(registry)); - // deploy new nft contract - nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); - nftContract.mint(address(this)); - nftContract.mint(address(this)); - nftContract.mint(address(this)); - - nftContract.approve(address(bridge), 0); - nftContract.approve(address(bridge), 1); - nftContract.approve(address(bridge), 2); - - // get virtual assets - registry.convert( - ethAsset, - emptyAsset, - virtualAsset1, - emptyAsset, - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - address(0x0) - ); - uint256 inputAmount = uint160(address(registeredAddress)); - // register an address - registry.convert( - virtualAsset1, - emptyAsset, - virtualAsset1, - emptyAsset, - inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - address(0x0) - ); - - // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) - vm.deal(address(bridge), 0); - - vm.label(address(bridge), "Basic NFT Vault Bridge"); - } - - function testInvalidCaller(address _callerAddress) public { - vm.assume(_callerAddress != rollupProcessor); - // Use HEVM cheatcode to call from a different address than is address(this) - vm.prank(_callerAddress); - vm.expectRevert(ErrorLib.InvalidCaller.selector); - bridge.convert( - emptyAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); - } - - function testInvalidInputAssetType() public { - vm.expectRevert(ErrorLib.InvalidInputA.selector); - bridge.convert( - emptyAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); - } - - function testInvalidOutputAssetType() public { - vm.expectRevert(ErrorLib.InvalidOutputA.selector); - bridge.convert( - ethAsset, - emptyAsset, - ethAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); - } - - // @notice The purpose of this test is to directly test convert functionality of the bridge. - // @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256. - function testGetVirtualAssetUnitTest() public { - vm.warp(block.timestamp + 1 days); - - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - ethAsset, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty - virtualAsset100, // _outputAssetA - in this example equal to input asset - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - address(0) // _rollupBeneficiary - address, the subsidy will be sent to - ); - - assertEq(outputValueA, 1, "Output value A doesn't equal 1"); - assertEq(outputValueB, 0, "Output value B is not 0"); - assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - } - - function testDepositandWithdraw() public { - vm.warp(block.timestamp + 1 days); - - address collection = address(nftContract); - address from = address(this); - - bridge.matchDeposit(virtualAsset100.id, collection, from, tokenToDeposit); - - (address returnedCollection, uint256 returnedId) = bridge.tokens( - virtualAsset100.id - ); - - assertEq(returnedId, tokenToDeposit, "nft token id does not match input"); - assertEq( - returnedCollection, - collection, - "collection data does not match" - ); - - uint64 auxData = registry.id() - 1; - - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - virtualAsset100, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty - virtualAsset100, // _outputAssetA - in this example equal to input asset - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - auxData, // _auxData - not used in the example bridge - address(0) // _rollupBeneficiary - address, the subsidy will be sent to - ); - - address owner = nftContract.ownerOf(tokenToDeposit); - - assertEq(registeredAddress, owner, "registered address is not the owner"); - assertEq(outputValueA, 0, "Output value A is not 0"); - assertEq(outputValueB, 0, "Output value B is not 0"); - assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - } -} From 69463ee2d9bc4306044e0cb11dac4a8436b497d0 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 16:16:37 -0500 Subject: [PATCH 17/65] cleanup comments --- .../bridges/registry/AddressRegistryE2E.t.sol | 24 ++----------------- .../registry/AddressRegistryUnitTest.t.sol | 4 ---- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index d3d2cf92f..2452cbf66 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -14,11 +14,8 @@ import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). */ contract AddressRegistryE2ETest is BridgeTestBase { - // address private constant BENEFICIARY = address(11); - // The reference to the example bridge AddressRegistry internal bridge; - // To store the id of the example bridge after being added uint256 private id; AztecTypes.AztecAsset private ethAsset; AztecTypes.AztecAsset private virtualAsset1; @@ -27,17 +24,14 @@ contract AddressRegistryE2ETest is BridgeTestBase { event logAddress(address); function setUp() public { - // Deploy a new example bridge bridge = new AddressRegistry(address(ROLLUP_PROCESSOR)); ethAsset = ROLLUP_ENCODER.getRealAztecAsset(address(0)); - // Define input and output assets virtualAsset1 = AztecTypes.AztecAsset({ id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL }); - // Use the label cheatcode to mark the address with "Example Bridge" in the traces vm.label(address(bridge), "Address Registry Bridge"); // Impersonate the multi-sig to add a new bridge @@ -46,7 +40,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { // List the example-bridge with a gasLimit of 120k // WARNING: If you set this value too low the interaction will fail for seemingly no reason! // OTOH if you se it too high bridge users will pay too much - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 1200000); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); vm.stopPrank(); @@ -57,8 +51,6 @@ contract AddressRegistryE2ETest is BridgeTestBase { function testGetVirtualAssets() public { vm.warp(block.timestamp + 1 days); - // Computes the encoded data for the specific bridge interaction - // uint256 bridgeCallData = ROLLUP_ENCODER.defiInteractionL2( id, ethAsset, @@ -68,19 +60,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { 0, 1 ); - - // bytes memory err = abi.encodePacked(ErrorLib.InvalidAuxData.selector); - - // ROLLUP_ENCODER.registerEventToBeChecked( - // bridgeCallData, - // ROLLUP_ENCODER.getNextNonce(), - // 0, - // maxInt, - // 0, - // true, - // err - // ); - + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. ( uint256 outputValueA, diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 4b1bd6579..974aeaeca 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -25,12 +25,8 @@ contract AddressRegistryUnitTest is BridgeTestBase { // In unit tests we set address of rollupProcessor to the address of this test contract rollupProcessor = address(this); - // Deploy a new example bridge bridge = new AddressRegistry(rollupProcessor); - // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) - // vm.deal(address(bridge), 0); - // Use the label cheatcode to mark the address with "AddressRegistry Bridge" in the traces vm.label(address(bridge), "AddressRegistry Bridge"); } From c3b5ce08fe5821a510ff2620b6e024c2970639c3 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 19:39:34 -0500 Subject: [PATCH 18/65] fmt --- src/bridges/nft-basic/NftVault.sol | 44 ++---- src/bridges/registry/AddressRegistry.sol | 29 ++-- .../bridges/nft-basic/NftVaultBasicE2E.t.sol | 103 ++---------- .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 149 +++++------------- .../bridges/registry/AddressRegistryE2E.t.sol | 57 ++----- .../registry/AddressRegistryUnitTest.t.sol | 142 +++++------------ 6 files changed, 137 insertions(+), 387 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index f8c7153c0..6afe159db 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -12,21 +12,19 @@ import {AddressRegistry} from "../registry/AddressRegistry.sol"; * @title Basic NFT Vault for Aztec. * @author Aztec Team * @notice You can use this contract to hold your NFTs on Aztec. Whoever holds the corresponding virutal asset note can withdraw the NFT. - * @dev This bridge demonstrates basic functionality for an NFT bridge. This may be extended to support more features. + * @dev This bridge demonstrates basic functionality for an NFT bridge. This may be extended to support more features. */ contract NftVault is BridgeBase { struct NftAsset { address collection; uint256 id; } + mapping(uint256 => NftAsset) public tokens; AddressRegistry public registry; - constructor( - address _rollupProcessor, - address _registry - ) BridgeBase(_rollupProcessor) { + constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { registry = AddressRegistry(_registry); } @@ -42,7 +40,7 @@ contract NftVault is BridgeBase { ) external payable - override( + override ( // uint64 _auxData, // address _rollupBeneficiary BridgeBase @@ -51,18 +49,18 @@ contract NftVault is BridgeBase { returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || - _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED + || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); if ( - _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || - _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED + || _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidOutputA(); // DEPOSIT // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && - _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH + && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { require(_totalInputValue == 1, "send only 1 wei"); // tokens[_interactionNonce] = NftAsset({ @@ -73,8 +71,8 @@ contract NftVault is BridgeBase { } // WITHDRAW else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && - _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { NftAsset memory token = tokens[_inputAssetA.id]; require(token.collection != address(0x0), "NFT doesn't exist"); @@ -82,29 +80,17 @@ contract NftVault is BridgeBase { address _to = registry.addresses(_auxData); require(_to != address(0x0), "unregistered withdraw address"); - IERC721(token.collection).transferFrom( - address(this), - _to, - token.id - ); + IERC721(token.collection).transferFrom(address(this), _to, token.id); delete tokens[_inputAssetA.id]; return (0, 0, false); } } // user must approve their NFT to be transferred by this contract before calling this function - function matchDeposit( - uint256 _virtualAssetId, - address _collection, - address _from, - uint256 _tokenId - ) external { + function matchDeposit(uint256 _virtualAssetId, address _collection, address _from, uint256 _tokenId) external { NftAsset memory asset = tokens[_virtualAssetId]; require(asset.collection == address(0x0), "Asset registered"); IERC721(_collection).transferFrom(_from, address(this), _tokenId); - tokens[_virtualAssetId] = NftAsset({ - collection: _collection, - id: _tokenId - }); + tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); } } diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index e179d14a3..1e2c0fb60 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -14,15 +14,11 @@ import {BridgeBase} from "../base/BridgeBase.sol"; * @dev Use this contract to lookup ethereum addresses by id. */ contract AddressRegistry is BridgeBase { - uint64 public id; mapping(uint64 => address) public addresses; uint256 public maxInt = type(uint160).max; - event AddressRegistered( - uint64 indexed id, - address indexed registeredAddress - ); + event AddressRegistered(uint64 indexed id, address indexed registeredAddress); /** * @notice Set address of rollup processor @@ -39,32 +35,27 @@ contract AddressRegistry is BridgeBase { uint256, uint64, address - ) - external - payable - override(BridgeBase) - onlyRollup - returns (uint256 outputValueA, uint256, bool) - { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || - _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED + || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); - if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) + if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) { revert ErrorLib.InvalidOutputA(); + } // get virtual assets if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && - _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH + && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { require(_totalInputValue == 1, "send only 1 wei"); return (maxInt, 0, false); } // register address with virtual asset else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && - _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { address toRegister = address(uint160(_totalInputValue)); addresses[id] = toRegister; diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index f57558014..586b29735 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -9,7 +9,8 @@ import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecType import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; -import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; +import {ERC721PresetMinterPauserAutoId} from + "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; /** * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment @@ -24,28 +25,15 @@ contract NftVaultBasicE2ETest is BridgeTestBase { uint256 private id; uint256 private registryBridgeId; uint256 private tokenIdToDeposit = 1; - address private constant registeredAddress = - 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; AztecTypes.AztecAsset private ethAsset; AztecTypes.AztecAsset private virtualAsset1 = - AztecTypes.AztecAsset({ - id: 1, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); + AztecTypes.AztecAsset({id: 1, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); AztecTypes.AztecAsset private virtualAsset100 = - AztecTypes.AztecAsset({ - id: 100, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); + AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); AztecTypes.AztecAsset private erc20InputAsset = - AztecTypes.AztecAsset({ - id: 1, - erc20Address: DAI, - assetType: AztecTypes.AztecAssetType.ERC20 - }); + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); function setUp() public { // deploy address registry @@ -82,48 +70,22 @@ contract NftVaultBasicE2ETest is BridgeTestBase { id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); // get virutal assets to register an address - ROLLUP_ENCODER.defiInteractionL2( - registryBridgeId, - ethAsset, - emptyAsset, - virtualAsset1, - emptyAsset, - 0, - 1 - ); + ROLLUP_ENCODER.defiInteractionL2(registryBridgeId, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); ROLLUP_ENCODER.processRollupAndGetBridgeResult(); // register an address uint160 inputAmount = uint160(registeredAddress); ROLLUP_ENCODER.defiInteractionL2( - registryBridgeId, - virtualAsset1, - emptyAsset, - virtualAsset1, - emptyAsset, - 0, - inputAmount + registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount ); ROLLUP_ENCODER.processRollupAndGetBridgeResult(); } function testDeposit() public { // get virtual asset before deposit - ROLLUP_ENCODER.defiInteractionL2( - id, - ethAsset, - emptyAsset, - virtualAsset100, - emptyAsset, - 0, - 1 - ); + ROLLUP_ENCODER.defiInteractionL2(id, ethAsset, emptyAsset, virtualAsset100, emptyAsset, 0, 1); - ( - uint256 outputValueA, - uint256 outputValueB, - bool isAsync - ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); assertEq(outputValueA, 1, "Output value A doesn't equal 1"); assertEq(outputValueB, 0, "Output value B is not 0"); @@ -132,51 +94,20 @@ contract NftVaultBasicE2ETest is BridgeTestBase { // match deposit address collection = address(nftContract); address from = address(this); - bridge.matchDeposit( - virtualAsset100.id, - collection, - from, - tokenIdToDeposit - ); - (address returnedCollection, uint256 returnedId) = bridge.tokens( - virtualAsset100.id - ); - assertEq( - returnedId, - tokenIdToDeposit, - "nft token id does not match input" - ); - assertEq( - returnedCollection, - collection, - "collection data does not match" - ); + bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); + (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); + assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); + assertEq(returnedCollection, collection, "collection data does not match"); } function testWithdraw() public { testDeposit(); uint64 auxData = registry.id() - 1; - ROLLUP_ENCODER.defiInteractionL2( - id, - virtualAsset100, - emptyAsset, - ethAsset, - emptyAsset, - auxData, - 1 - ); + ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); - ( - uint256 outputValueA, - uint256 outputValueB, - bool isAsync - ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); address owner = nftContract.ownerOf(tokenIdToDeposit); - assertEq( - registeredAddress, - owner, - "registered address is not the owner" - ); + assertEq(registeredAddress, owner, "registered address is not the owner"); assertEq(outputValueA, 0, "Output value A is not 0"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index 1602b25fa..42b75d909 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -6,7 +6,8 @@ import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; // Example-specific imports -import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; +import {ERC721PresetMinterPauserAutoId} from + "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; @@ -24,34 +25,17 @@ contract NftVaultBasicUnitTest is BridgeTestBase { ERC721PresetMinterPauserAutoId private nftContract; uint256 private tokenIdToDeposit = 1; AddressRegistry private registry; - address private constant registeredAddress = - 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; AztecTypes.AztecAsset private ethAsset = - AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.ETH - }); + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); AztecTypes.AztecAsset private virtualAsset1 = - AztecTypes.AztecAsset({ - id: 1, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); + AztecTypes.AztecAsset({id: 1, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); AztecTypes.AztecAsset private virtualAsset100 = - AztecTypes.AztecAsset({ - id: 100, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); + AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); AztecTypes.AztecAsset private erc20InputAsset = - AztecTypes.AztecAsset({ - id: 1, - erc20Address: DAI, - assetType: AztecTypes.AztecAssetType.ERC20 - }); + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); event log(string, address); @@ -111,61 +95,33 @@ contract NftVaultBasicUnitTest is BridgeTestBase { // Use HEVM cheatcode to call from a different address than is address(this) vm.prank(_callerAddress); vm.expectRevert(ErrorLib.InvalidCaller.selector); - bridge.convert( - emptyAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); } function testInvalidInputAssetType() public { vm.expectRevert(ErrorLib.InvalidInputA.selector); - bridge.convert( - emptyAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); } function testInvalidOutputAssetType() public { vm.expectRevert(ErrorLib.InvalidOutputA.selector); - bridge.convert( - ethAsset, - emptyAsset, - erc20InputAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(ethAsset, emptyAsset, erc20InputAsset, emptyAsset, 0, 0, 0, address(0)); } // @notice The purpose of this test is to directly test convert functionality of the bridge. function testGetVirtualAssetUnitTest() public { vm.warp(block.timestamp + 1 days); - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - ethAsset, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty - virtualAsset100, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - address(0) // _rollupBeneficiary - address, the subsidy will be sent to - ); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + ethAsset, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData + address(0) // _rollupBeneficiary - address, the subsidy will be sent to + ); assertEq(outputValueA, 1, "Output value A doesn't equal 1"); assertEq(outputValueB, 0, "Output value B is not 0"); @@ -194,25 +150,10 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address collection = address(nftContract); address from = address(this); - bridge.matchDeposit( - virtualAsset100.id, - collection, - from, - tokenIdToDeposit - ); - (address returnedCollection, uint256 returnedId) = bridge.tokens( - virtualAsset100.id - ); - assertEq( - returnedId, - tokenIdToDeposit, - "nft token id does not match input" - ); - assertEq( - returnedCollection, - collection, - "collection data does not match" - ); + bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); + (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); + assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); + assertEq(returnedCollection, collection, "collection data does not match"); } function testDepositFailWithDuplicateNft() public { @@ -224,34 +165,24 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.expectRevert(); // should fail because an NFT with this id has already been deposited - bridge.matchDeposit( - virtualAsset100.id, - collection, - from, - tokenIdToDeposit - ); + bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); } function testWithdraw() public { testDeposit(); uint64 auxData = registry.id() - 1; - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - virtualAsset100, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty - ethAsset, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - auxData, // _auxData - the id of the eth address to withdraw to from the registry - address(0) - ); - address owner = nftContract.ownerOf(tokenIdToDeposit); - assertEq( - registeredAddress, - owner, - "registered address is not the owner" + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + virtualAsset100, // _inputAssetA - definition of an input asset + emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _outputAssetA + emptyAsset, // _outputAssetB - not used so can be left empty + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + auxData, // _auxData - the id of the eth address to withdraw to from the registry + address(0) ); + address owner = nftContract.ownerOf(tokenIdToDeposit); + assertEq(registeredAddress, owner, "registered address is not the owner"); assertEq(outputValueA, 0, "Output value A is not 0"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); @@ -269,12 +200,12 @@ contract NftVaultBasicUnitTest is BridgeTestBase { bridge.convert( virtualAsset1, // _inputAssetA - definition of an input asset emptyAsset, // _inputAssetB - not used so can be left empty - ethAsset, // _outputAssetA + ethAsset, // _outputAssetA emptyAsset, // _outputAssetB - not used so can be left empty 1, // _totalInputValue - an amount of input asset A sent to the bridge 0, // _interactionNonce auxData, - address(0) + address(0) ); } @@ -286,12 +217,12 @@ contract NftVaultBasicUnitTest is BridgeTestBase { bridge.convert( virtualAsset1, // _inputAssetA - definition of an input asset emptyAsset, // _inputAssetB - not used so can be left empty - ethAsset, // _outputAssetA + ethAsset, // _outputAssetA emptyAsset, // _outputAssetB - not used so can be left empty 1, // _totalInputValue - an amount of input asset A sent to the bridge 0, // _interactionNonce auxData, - address(0) + address(0) ); } } diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 2452cbf66..3ed945da2 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -14,23 +14,20 @@ import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). */ contract AddressRegistryE2ETest is BridgeTestBase { - AddressRegistry internal bridge; uint256 private id; AztecTypes.AztecAsset private ethAsset; AztecTypes.AztecAsset private virtualAsset1; uint256 public maxInt = type(uint160).max; - event log(string, uint); + + event log(string, uint256); event logAddress(address); function setUp() public { bridge = new AddressRegistry(address(ROLLUP_PROCESSOR)); ethAsset = ROLLUP_ENCODER.getRealAztecAsset(address(0)); - virtualAsset1 = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); + virtualAsset1 = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); vm.label(address(bridge), "Address Registry Bridge"); @@ -51,22 +48,10 @@ contract AddressRegistryE2ETest is BridgeTestBase { function testGetVirtualAssets() public { vm.warp(block.timestamp + 1 days); - ROLLUP_ENCODER.defiInteractionL2( - id, - ethAsset, - emptyAsset, - virtualAsset1, - emptyAsset, - 0, - 1 - ); - + ROLLUP_ENCODER.defiInteractionL2(id, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); + // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - ( - uint256 outputValueA, - uint256 outputValueB, - bool isAsync - ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); // Check the output values are as expected assertEq(outputValueA, maxInt, "outputValueA doesn't equal maxInt"); @@ -75,37 +60,19 @@ contract AddressRegistryE2ETest is BridgeTestBase { } function testRegistration() public { - uint160 inputAmount = uint160( - 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA - ); - - ROLLUP_ENCODER.defiInteractionL2( - id, - virtualAsset1, - emptyAsset, - virtualAsset1, - emptyAsset, - 0, - inputAmount - ); + uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + + ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount); // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. - ( - uint256 outputValueA, - uint256 outputValueB, - bool isAsync - ) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); uint64 addressId = bridge.id(); uint64 registeredId = addressId - 1; address newlyRegistered = bridge.addresses(registeredId); // Check the output values are as expected - assertEq( - address(inputAmount), - newlyRegistered, - "input amount doesn't equal newly registered address" - ); + assertEq(address(inputAmount), newlyRegistered, "input amount doesn't equal newly registered address"); assertEq(outputValueA, 0, "Non-zero outputValueA"); assertEq(outputValueB, 0, "Non-zero outputValueB"); assertFalse(isAsync, "Bridge is not synchronous"); diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 974aeaeca..01e6c8766 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -36,89 +36,46 @@ contract AddressRegistryUnitTest is BridgeTestBase { // Use HEVM cheatcode to call from a different address than is address(this) vm.prank(_callerAddress); vm.expectRevert(ErrorLib.InvalidCaller.selector); - bridge.convert( - emptyAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); } function testInvalidInputAssetType() public { - AztecTypes.AztecAsset memory inputAsset = AztecTypes.AztecAsset({ - id: 1, - erc20Address: DAI, - assetType: AztecTypes.AztecAssetType.ERC20 - }); + AztecTypes.AztecAsset memory inputAsset = + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); vm.expectRevert(ErrorLib.InvalidInputA.selector); - bridge.convert( - inputAsset, - emptyAsset, - emptyAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(inputAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); } function testInvalidOutputAssetType() public { - AztecTypes.AztecAsset memory inputAsset = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.ETH - }); - AztecTypes.AztecAsset memory outputAsset = AztecTypes.AztecAsset({ - id: 1, - erc20Address: DAI, - assetType: AztecTypes.AztecAssetType.ERC20 - }); + AztecTypes.AztecAsset memory inputAsset = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + AztecTypes.AztecAsset memory outputAsset = + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); vm.expectRevert(ErrorLib.InvalidOutputA.selector); - bridge.convert( - inputAsset, - emptyAsset, - outputAsset, - emptyAsset, - 0, - 0, - 0, - address(0) - ); + bridge.convert(inputAsset, emptyAsset, outputAsset, emptyAsset, 0, 0, 0, address(0)); } // @notice The purpose of this test is to directly test convert functionality of the bridge. function testGetBackMaxVirtualAssets() public { vm.warp(block.timestamp + 1 days); - AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.ETH - }); - - AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - inputAssetA, - emptyAsset, - outputAssetA, - emptyAsset, - 1, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - address(0x0) - ); + AztecTypes.AztecAsset memory inputAssetA = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + + AztecTypes.AztecAsset memory outputAssetA = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + inputAssetA, + emptyAsset, + outputAssetA, + emptyAsset, + 1, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) + ); assertEq(outputValueA, maxInt, "Output value A doesn't equal maxInt"); assertEq(outputValueB, 0, "Output value B is not 0"); @@ -129,41 +86,28 @@ contract AddressRegistryUnitTest is BridgeTestBase { vm.warp(block.timestamp + 1 days); // Define input and output assets - AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - - AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset({ - id: 0, - erc20Address: address(0), - assetType: AztecTypes.AztecAssetType.VIRTUAL - }); - - uint160 inputAmount = uint160( - 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA - ); + AztecTypes.AztecAsset memory inputAssetA = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge - .convert( - inputAssetA, - emptyAsset, - outputAssetA, - emptyAsset, - inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge - 0, // _interactionNonce - 0, // _auxData - not used in the example bridge - address(0x0) - ); + AztecTypes.AztecAsset memory outputAssetA = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - address newlyRegistered = bridge.addresses(0); + uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); - assertEq( - address(inputAmount), - newlyRegistered, - "Address not registered" + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + inputAssetA, + emptyAsset, + outputAssetA, + emptyAsset, + inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + 0, // _interactionNonce + 0, // _auxData - not used in the example bridge + address(0x0) ); + + address newlyRegistered = bridge.addresses(0); + + assertEq(address(inputAmount), newlyRegistered, "Address not registered"); assertEq(outputValueA, 0, "Output value is not 0"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); From 0ab54065cbff9530928951a079e12c7539eec0b6 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 19:45:10 -0500 Subject: [PATCH 19/65] add L1 option --- src/bridges/registry/AddressRegistry.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 1e2c0fb60..5f76c06e8 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -66,4 +66,11 @@ contract AddressRegistry is BridgeBase { revert(); } } + + function registerWithdrawAddress(address _to) external returns (uint256) { + id++; + addresses[id] = _to; + emit AddressRegistered(id, _to); + return id; + } } From 1288f976f1f1b93d66a1d6ccf6843a819af97154 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 2 Dec 2022 19:46:50 -0500 Subject: [PATCH 20/65] update inc --- src/bridges/registry/AddressRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 5f76c06e8..ac496d39b 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -68,8 +68,8 @@ contract AddressRegistry is BridgeBase { } function registerWithdrawAddress(address _to) external returns (uint256) { - id++; addresses[id] = _to; + id++; emit AddressRegistered(id, _to); return id; } From b845e70a46cff2253de88643afd86b93e1ade6d8 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:05:31 -0500 Subject: [PATCH 21/65] remove comments, fix matchDeposit --- src/bridges/nft-basic/NftVault.sol | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 6afe159db..b68c6d745 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -21,8 +21,7 @@ contract NftVault is BridgeBase { } mapping(uint256 => NftAsset) public tokens; - - AddressRegistry public registry; + AddressRegistry public immutable registry; constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { registry = AddressRegistry(_registry); @@ -34,7 +33,7 @@ contract NftVault is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint256 _totalInputValue, - uint256 _interactionNonce, + uint256, uint64 _auxData, address ) @@ -56,21 +55,13 @@ contract NftVault is BridgeBase { _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidOutputA(); - // DEPOSIT - // return virutal asset id, will not actually match to NFT until matchDeposit is called from ethereum if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { require(_totalInputValue == 1, "send only 1 wei"); - // tokens[_interactionNonce] = NftAsset({ - // collection: address(0x0), - // id: 0 - // }); return (1, 0, false); - } - // WITHDRAW - else if ( + } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { @@ -86,11 +77,9 @@ contract NftVault is BridgeBase { } } - // user must approve their NFT to be transferred by this contract before calling this function - function matchDeposit(uint256 _virtualAssetId, address _collection, address _from, uint256 _tokenId) external { - NftAsset memory asset = tokens[_virtualAssetId]; - require(asset.collection == address(0x0), "Asset registered"); - IERC721(_collection).transferFrom(_from, address(this), _tokenId); + function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { + require(tokens[_virtualAssetId].collection == address(0x0), "Asset registered"); tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); + IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); } } From 217a526d15f5b882f1aa320feac8117fb14cd73c Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:06:04 -0500 Subject: [PATCH 22/65] rename id, cleanup --- src/bridges/registry/AddressRegistry.sol | 26 ++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index ac496d39b..a454e9096 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -14,11 +14,10 @@ import {BridgeBase} from "../base/BridgeBase.sol"; * @dev Use this contract to lookup ethereum addresses by id. */ contract AddressRegistry is BridgeBase { - uint64 public id; - mapping(uint64 => address) public addresses; - uint256 public maxInt = type(uint160).max; + uint64 public addressCount; + mapping(uint256 => address) public addresses; - event AddressRegistered(uint64 indexed id, address indexed registeredAddress); + event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); /** * @notice Set address of rollup processor @@ -43,24 +42,21 @@ contract AddressRegistry is BridgeBase { if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) { revert ErrorLib.InvalidOutputA(); } - - // get virtual assets if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { require(_totalInputValue == 1, "send only 1 wei"); - return (maxInt, 0, false); + return (type(uint160).max, 0, false); } - // register address with virtual asset else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { + addressCount++; address toRegister = address(uint160(_totalInputValue)); - addresses[id] = toRegister; - emit AddressRegistered(id, toRegister); - id++; + addresses[addressCount] = toRegister; + emit AddressRegistered(addressCount, toRegister); return (0, 0, false); } else { revert(); @@ -68,9 +64,9 @@ contract AddressRegistry is BridgeBase { } function registerWithdrawAddress(address _to) external returns (uint256) { - addresses[id] = _to; - id++; - emit AddressRegistered(id, _to); - return id; + addressCount++; + addresses[addressCount] = _to; + emit AddressRegistered(addressCount, _to); + return addressCount; } } From 43553530795c5eefa5570c75f149d5ae65ca0cb8 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:06:52 -0500 Subject: [PATCH 23/65] update tests --- src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol | 8 ++++---- src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index 586b29735..db3f47154 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.4; import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; // Example-specific imports import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; @@ -93,8 +93,8 @@ contract NftVaultBasicE2ETest is BridgeTestBase { // match deposit address collection = address(nftContract); - address from = address(this); - bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); + + bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -102,7 +102,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { function testWithdraw() public { testDeposit(); - uint64 auxData = registry.id() - 1; + uint64 auxData = registry.addressCount(); ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index 42b75d909..d61366974 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -149,8 +149,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.warp(block.timestamp + 1 days); address collection = address(nftContract); - address from = address(this); - bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); + bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -161,16 +160,15 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.warp(block.timestamp + 1 days); address collection = address(nftContract); - address from = address(this); vm.expectRevert(); // should fail because an NFT with this id has already been deposited - bridge.matchDeposit(virtualAsset100.id, collection, from, tokenIdToDeposit); + bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); } function testWithdraw() public { testDeposit(); - uint64 auxData = registry.id() - 1; + uint64 auxData = registry.addressCount(); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( virtualAsset100, // _inputAssetA - definition of an input asset emptyAsset, // _inputAssetB - not used so can be left empty @@ -194,7 +192,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { function testWithdrawUnregisteredNft() public { testDeposit(); - uint64 auxData = registry.id() - 1; + uint64 auxData = registry.addressCount(); vm.expectRevert(); // should fail because no NFT has been registered with this virtual asset bridge.convert( From 65595762eab69027ebf6eb47e066dc9316fff2cc Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:07:01 -0500 Subject: [PATCH 24/65] check event --- src/test/bridges/registry/AddressRegistryE2E.t.sol | 12 +++++++----- .../bridges/registry/AddressRegistryUnitTest.t.sol | 10 ++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 3ed945da2..7644ece08 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -20,8 +20,7 @@ contract AddressRegistryE2ETest is BridgeTestBase { AztecTypes.AztecAsset private virtualAsset1; uint256 public maxInt = type(uint160).max; - event log(string, uint256); - event logAddress(address); + event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); function setUp() public { bridge = new AddressRegistry(address(ROLLUP_PROCESSOR)); @@ -61,14 +60,17 @@ contract AddressRegistryE2ETest is BridgeTestBase { function testRegistration() public { uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); - + + vm.expectEmit(true, true, false, false); + emit AddressRegistered(1, address(inputAmount)); + ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount); // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - uint64 addressId = bridge.id(); - uint64 registeredId = addressId - 1; + uint64 addressId = bridge.addressCount(); + uint64 registeredId = addressId; address newlyRegistered = bridge.addresses(registeredId); // Check the output values are as expected diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 01e6c8766..2e8b47a7c 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.4; import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; -import {AztecTypes} from "../../../../lib/rollup-encoder/src/libraries/AztecTypes.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; // Example-specific imports import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; @@ -17,6 +17,8 @@ contract AddressRegistryUnitTest is BridgeTestBase { uint256 public maxInt = type(uint160).max; AztecTypes.AztecAsset private ethAsset; + event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); + // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real // rollup processor would. function receiveEthFromBridge(uint256 _interactionNonce) external payable {} @@ -94,6 +96,9 @@ contract AddressRegistryUnitTest is BridgeTestBase { uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + vm.expectEmit(true, true, false, false); + emit AddressRegistered(1, address(inputAmount)); + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( inputAssetA, emptyAsset, @@ -105,7 +110,8 @@ contract AddressRegistryUnitTest is BridgeTestBase { address(0x0) ); - address newlyRegistered = bridge.addresses(0); + uint256 id = bridge.addressCount(); + address newlyRegistered = bridge.addresses(id); assertEq(address(inputAmount), newlyRegistered, "Address not registered"); assertEq(outputValueA, 0, "Output value is not 0"); From cfe88ae41281e1dd1766dfc168e5f356c21b5bcf Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:12:35 -0500 Subject: [PATCH 25/65] fmt --- src/bridges/registry/AddressRegistry.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index a454e9096..27412ceaf 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -48,8 +48,7 @@ contract AddressRegistry is BridgeBase { ) { require(_totalInputValue == 1, "send only 1 wei"); return (type(uint160).max, 0, false); - } - else if ( + } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { From a5d67053a5feb8439262161a7d7caf01171b1209 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:14:16 -0500 Subject: [PATCH 26/65] clean up comments --- .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 75 +++++++++---------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index d61366974..ec2f93f7f 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -20,7 +20,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { } address private rollupProcessor; - // The reference to the example bridge + NftVault private bridge; ERC721PresetMinterPauserAutoId private nftContract; uint256 private tokenIdToDeposit = 1; @@ -46,11 +46,9 @@ contract NftVaultBasicUnitTest is BridgeTestBase { function setUp() public { // In unit tests we set address of rollupProcessor to the address of this test contract rollupProcessor = address(this); - // deploy address registry + registry = new AddressRegistry(rollupProcessor); - // Deploy a new nft vault bridge bridge = new NftVault(rollupProcessor, address(registry)); - // deploy new nft contract nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); nftContract.mint(address(this)); @@ -66,9 +64,9 @@ contract NftVaultBasicUnitTest is BridgeTestBase { emptyAsset, virtualAsset1, emptyAsset, - 1, // _totalInputValue - an amount of input asset A sent to the bridge + 1, // _totalInputValue 0, // _interactionNonce - 0, // _auxData - not used + 0, // _auxData address(0x0) ); uint256 inputAmount = uint160(address(registeredAddress)); @@ -78,15 +76,14 @@ contract NftVaultBasicUnitTest is BridgeTestBase { emptyAsset, virtualAsset1, emptyAsset, - inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + inputAmount, 0, // _interactionNonce - 0, // _auxData - not used in the example bridge + 0, // _auxData address(0x0) ); - // Set ETH balance of bridge and BENEFICIARY to 0 for clarity (somebody sent ETH to that address on mainnet) + // Set ETH balance of bridge to 0 for clarity (somebody sent ETH to that address on mainnet) vm.deal(address(bridge), 0); - vm.label(address(bridge), "Basic NFT Vault Bridge"); } @@ -108,19 +105,18 @@ contract NftVaultBasicUnitTest is BridgeTestBase { bridge.convert(ethAsset, emptyAsset, erc20InputAsset, emptyAsset, 0, 0, 0, address(0)); } - // @notice The purpose of this test is to directly test convert functionality of the bridge. function testGetVirtualAssetUnitTest() public { vm.warp(block.timestamp + 1 days); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - ethAsset, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _inputAssetA + emptyAsset, // _inputAssetB virtualAsset100, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge + emptyAsset, // _outputAssetB + 1, // _totalInputValue 0, // _interactionNonce 0, // _auxData - address(0) // _rollupBeneficiary - address, the subsidy will be sent to + address(0) // _rollupBeneficiary ); assertEq(outputValueA, 1, "Output value A doesn't equal 1"); @@ -128,20 +124,20 @@ contract NftVaultBasicUnitTest is BridgeTestBase { assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); } + // should fail because sending more than 1 wei function testGetVirtualAssetShouldFail() public { vm.warp(block.timestamp + 1 days); vm.expectRevert(); - // should fail because sending more than 1 wei bridge.convert( - ethAsset, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty + ethAsset, // _inputAssetA + emptyAsset, // _inputAssetB virtualAsset100, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 2, // _totalInputValue - an amount of input asset A sent to the bridge + emptyAsset, // _outputAssetB + 2, // _totalInputValue 0, // _interactionNonce - 0, // _auxData - not used in this call - address(0) // _rollupBeneficiary - address, the subsidy will be sent to + 0, // _auxData + address(0) // _rollupBeneficiary ); } @@ -155,14 +151,13 @@ contract NftVaultBasicUnitTest is BridgeTestBase { assertEq(returnedCollection, collection, "collection data does not match"); } + // should fail because an NFT with this id has already been deposited function testDepositFailWithDuplicateNft() public { testDeposit(); vm.warp(block.timestamp + 1 days); address collection = address(nftContract); - vm.expectRevert(); - // should fail because an NFT with this id has already been deposited bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); } @@ -170,13 +165,13 @@ contract NftVaultBasicUnitTest is BridgeTestBase { testDeposit(); uint64 auxData = registry.addressCount(); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - virtualAsset100, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset100, // _inputAssetA + emptyAsset, // _inputAssetB ethAsset, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge + emptyAsset, // _outputAssetB + 1, // _totalInputValue 0, // _interactionNonce - auxData, // _auxData - the id of the eth address to withdraw to from the registry + auxData, // _auxData address(0) ); address owner = nftContract.ownerOf(tokenIdToDeposit); @@ -190,34 +185,34 @@ contract NftVaultBasicUnitTest is BridgeTestBase { assertEq(_id, 0, "token id is not 0"); } + // should fail because no NFT has been registered with this virtual asset function testWithdrawUnregisteredNft() public { testDeposit(); uint64 auxData = registry.addressCount(); vm.expectRevert(); - // should fail because no NFT has been registered with this virtual asset bridge.convert( - virtualAsset1, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset1, // _inputAssetA + emptyAsset, // _inputAssetB ethAsset, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge + emptyAsset, // _outputAssetB + 1, // _totalInputValue 0, // _interactionNonce auxData, address(0) ); } + // should fail because no withdraw address has been registered with this id function testWithdrawUnregisteredWithdrawAddress() public { testDeposit(); uint64 auxData = 1000; vm.expectRevert(); - // should fail because no withdraw address has been registered with this id bridge.convert( - virtualAsset1, // _inputAssetA - definition of an input asset - emptyAsset, // _inputAssetB - not used so can be left empty + virtualAsset1, // _inputAssetA + emptyAsset, // _inputAssetB ethAsset, // _outputAssetA - emptyAsset, // _outputAssetB - not used so can be left empty - 1, // _totalInputValue - an amount of input asset A sent to the bridge + emptyAsset, // _outputAssetB + 1, // _totalInputValue 0, // _interactionNonce auxData, address(0) From a10c6ba0fc251006d37573e6ece78b05084b0902 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:14:26 -0500 Subject: [PATCH 27/65] clean up comments --- src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index db3f47154..7cce8a8da 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -36,9 +36,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); function setUp() public { - // deploy address registry registry = new AddressRegistry(address(ROLLUP_PROCESSOR)); - // Deploy a new nft vault bridge bridge = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); @@ -57,7 +55,6 @@ contract NftVaultBasicE2ETest is BridgeTestBase { // Impersonate the multi-sig to add a new bridge vm.startPrank(MULTI_SIG); - // List the example-bridge with a gasLimit of 120k // WARNING: If you set this value too low the interaction will fail for seemingly no reason! // OTOH if you se it too high bridge users will pay too much ROLLUP_PROCESSOR.setSupportedBridge(address(registry), 120000); @@ -91,9 +88,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - // match deposit address collection = address(nftContract); - bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); From 469c37253ee570e345a433d1f1684fa6398e3850 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:15:09 -0500 Subject: [PATCH 28/65] clean comments --- src/test/bridges/registry/AddressRegistryE2E.t.sol | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index 7644ece08..c59d2ac28 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -33,7 +33,6 @@ contract AddressRegistryE2ETest is BridgeTestBase { // Impersonate the multi-sig to add a new bridge vm.startPrank(MULTI_SIG); - // List the example-bridge with a gasLimit of 120k // WARNING: If you set this value too low the interaction will fail for seemingly no reason! // OTOH if you se it too high bridge users will pay too much ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); @@ -49,10 +48,8 @@ contract AddressRegistryE2ETest is BridgeTestBase { ROLLUP_ENCODER.defiInteractionL2(id, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - // Check the output values are as expected assertEq(outputValueA, maxInt, "outputValueA doesn't equal maxInt"); assertEq(outputValueB, 0, "Non-zero outputValueB"); assertFalse(isAsync, "Bridge is not synchronous"); @@ -60,20 +57,18 @@ contract AddressRegistryE2ETest is BridgeTestBase { function testRegistration() public { uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); - + vm.expectEmit(true, true, false, false); emit AddressRegistered(1, address(inputAmount)); - + ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount); - // Execute the rollup with the bridge interaction. Ensure that event as seen above is emitted. (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); uint64 addressId = bridge.addressCount(); uint64 registeredId = addressId; address newlyRegistered = bridge.addresses(registeredId); - // Check the output values are as expected assertEq(address(inputAmount), newlyRegistered, "input amount doesn't equal newly registered address"); assertEq(outputValueA, 0, "Non-zero outputValueA"); assertEq(outputValueB, 0, "Non-zero outputValueB"); From 281be8f1bd57354ab2d94575b257ad43733cd9c3 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 5 Dec 2022 20:17:43 -0500 Subject: [PATCH 29/65] clean comments --- .../bridges/registry/AddressRegistryUnitTest.t.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 2e8b47a7c..374870e5e 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -58,7 +58,6 @@ contract AddressRegistryUnitTest is BridgeTestBase { bridge.convert(inputAsset, emptyAsset, outputAsset, emptyAsset, 0, 0, 0, address(0)); } - // @notice The purpose of this test is to directly test convert functionality of the bridge. function testGetBackMaxVirtualAssets() public { vm.warp(block.timestamp + 1 days); @@ -73,9 +72,9 @@ contract AddressRegistryUnitTest is BridgeTestBase { emptyAsset, outputAssetA, emptyAsset, - 1, // _totalInputValue - an amount of input asset A sent to the bridge + 1, // _totalInputValue 0, // _interactionNonce - 0, // _auxData - not used in the example bridge + 0, // _auxData address(0x0) ); @@ -87,7 +86,6 @@ contract AddressRegistryUnitTest is BridgeTestBase { function testRegistringAnAddress() public { vm.warp(block.timestamp + 1 days); - // Define input and output assets AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); @@ -104,9 +102,9 @@ contract AddressRegistryUnitTest is BridgeTestBase { emptyAsset, outputAssetA, emptyAsset, - inputAmount, // _totalInputValue - an amount of input asset A sent to the bridge + inputAmount, // _totalInputValue 0, // _interactionNonce - 0, // _auxData - not used in the example bridge + 0, // _auxData address(0x0) ); From 5c2c0b3a69a5f7811c49f3f495b96497a6467d85 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 7 Dec 2022 20:25:57 -0500 Subject: [PATCH 30/65] add deposit/withdraw events --- src/bridges/nft-basic/NftVault.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index b68c6d745..1468c1b65 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -23,6 +23,9 @@ contract NftVault is BridgeBase { mapping(uint256 => NftAsset) public tokens; AddressRegistry public immutable registry; + event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { registry = AddressRegistry(_registry); } @@ -72,6 +75,7 @@ contract NftVault is BridgeBase { require(_to != address(0x0), "unregistered withdraw address"); IERC721(token.collection).transferFrom(address(this), _to, token.id); + emit NftWithdraw(_inputAssetA.id, token.collection, token.id); delete tokens[_inputAssetA.id]; return (0, 0, false); } @@ -81,5 +85,6 @@ contract NftVault is BridgeBase { require(tokens[_virtualAssetId].collection == address(0x0), "Asset registered"); tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); + emit NftDeposit(_virtualAssetId, _collection, _tokenId); } } From ad48137c76a3c673e59be7e9e11fbbde37ab526c Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 7 Dec 2022 20:26:18 -0500 Subject: [PATCH 31/65] revert reason for invalid input/outputs --- src/bridges/registry/AddressRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 27412ceaf..af914f7ce 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -58,7 +58,7 @@ contract AddressRegistry is BridgeBase { emit AddressRegistered(addressCount, toRegister); return (0, 0, false); } else { - revert(); + revert("invalid input/output types"); } } From 3473dd6e36409c83bc4594f1e45cc3e42a8366ed Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 7 Dec 2022 20:26:31 -0500 Subject: [PATCH 32/65] deployments --- .../nft-basic/NftVaultDeployment.s.sol | 42 +++++++++++++++++++ .../registry/AddressRegistryDeployment.s.sol | 28 +++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/deployment/nft-basic/NftVaultDeployment.s.sol create mode 100644 src/deployment/registry/AddressRegistryDeployment.s.sol diff --git a/src/deployment/nft-basic/NftVaultDeployment.s.sol b/src/deployment/nft-basic/NftVaultDeployment.s.sol new file mode 100644 index 000000000..0a6d0eda1 --- /dev/null +++ b/src/deployment/nft-basic/NftVaultDeployment.s.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BaseDeployment} from "../base/BaseDeployment.s.sol"; +import {NftVault} from "../../bridges/nft-basic/NftVault.sol"; +import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; + +contract NftVaultDeployment is BaseDeployment { + function deploy(address _addressRegistry) public returns (address) { + emit log("Deploying NftVault bridge"); + + vm.broadcast(); + NftVault bridge = new NftVault(ROLLUP_PROCESSOR, _addressRegistry); + + emit log_named_address("NftVault bridge deployed to", address(bridge)); + + return address(bridge); + } + + function deployAndList(address _addressRegistry) public returns (address) { + address bridge = deploy(_addressRegistry); + + uint256 addressId = listBridge(bridge, 400000); + emit log_named_uint("NftVault bridge address id", addressId); + + return bridge; + } + + function deployAndListAddressRegistry() public returns (address) { + emit log("Deploying AddressRegistry bridge"); + + vm.broadcast(); + AddressRegistry bridge = new AddressRegistry(ROLLUP_PROCESSOR); + + emit log_named_address("AddressRegistry bridge deployed to", address(bridge)); + uint256 addressId = listBridge(address(bridge), 400000); + emit log_named_uint("AddressRegistry bridge address id", addressId); + + return address(bridge); + } +} diff --git a/src/deployment/registry/AddressRegistryDeployment.s.sol b/src/deployment/registry/AddressRegistryDeployment.s.sol new file mode 100644 index 000000000..1f42a63ff --- /dev/null +++ b/src/deployment/registry/AddressRegistryDeployment.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {BaseDeployment} from "../base/BaseDeployment.s.sol"; +import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; + +contract AddressRegistryDeployment is BaseDeployment { + function deploy() public returns (address) { + emit log("Deploying AddressRegistry bridge"); + + vm.broadcast(); + AddressRegistry bridge = new AddressRegistry(ROLLUP_PROCESSOR); + + emit log_named_address("AddressRegistry bridge deployed to", address(bridge)); + + return address(bridge); + } + + function deployAndList() public returns (address) { + address bridge = deploy(); + + uint256 addressId = listBridge(bridge, 400000); + emit log_named_uint("AddressRegistry bridge address id", addressId); + + return bridge; + } +} From 1ae3752ae417d88bf45fe06404bc0ec78e7f02c3 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 7 Dec 2022 20:26:46 -0500 Subject: [PATCH 33/65] gas benchmarks --- src/gas/nft-basic/NftVaultGas.s.sol | 79 +++++++++++++++++++++++ src/gas/registry/AddressRegistryGas.s.sol | 54 ++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/gas/nft-basic/NftVaultGas.s.sol create mode 100644 src/gas/registry/AddressRegistryGas.s.sol diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol new file mode 100644 index 000000000..5a41224b1 --- /dev/null +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; +import {AddressRegistryDeployment} from "../../deployment/registry/AddressRegistryDeployment.s.sol"; +import {NftVault} from "../../bridges/nft-basic/NftVault.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +import {NftVaultDeployment} from "../../deployment/nft-basic/NftVaultDeployment.s.sol"; +import {GasBase} from "../base/GasBase.sol"; + +import {ERC721PresetMinterPauserAutoId} from + "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; + + +interface IRead { + function defiBridgeProxy() external view returns (address); +} + +contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { + GasBase internal gasBase; + NftVault internal bridge; + ERC721PresetMinterPauserAutoId internal nftContract; + address internal registry; + uint256 internal registryAddressId; + + function measure() public { + uint256 privKey1 = vm.envUint("PRIVATE_KEY"); + address addr1 = vm.addr(privKey1); + + address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); + vm.label(defiProxy, "DefiProxy"); + + vm.startBroadcast(); + gasBase = new GasBase(defiProxy); + nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); + nftContract.mint(addr1); + vm.stopBroadcast(); + + address temp = ROLLUP_PROCESSOR; + ROLLUP_PROCESSOR = address(gasBase); + registry = deployAndListAddressRegistry(); + address bridge = deployAndList(registry); + ROLLUP_PROCESSOR = temp; + + AztecTypes.AztecAsset memory empty; + AztecTypes.AztecAsset memory eth = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + AztecTypes.AztecAsset memory virtualAsset = + AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + + vm.startBroadcast(); + address(gasBase).call{value: 2 ether}(""); + + // get registry virtual asset + gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + // register address + gasBase.convert(address(registry), virtualAsset, empty, virtualAsset, empty, uint256(uint160(addr1)), 0, 0, address(0), 400000); + nftContract.approve(address(bridge), 0); + vm.stopBroadcast(); + + // Get virtual assets + { + vm.broadcast(); + gasBase.convert(bridge, eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + } + // deposit nft + { + vm.broadcast(); + NftVault(bridge).matchDeposit(virtualAsset.id, address(nftContract), 0); + } + // withdraw nft + { + vm.broadcast(); + gasBase.convert(bridge, virtualAsset, empty, eth, empty, 1, 0, 1, address(0), 400000); + } + } +} diff --git a/src/gas/registry/AddressRegistryGas.s.sol b/src/gas/registry/AddressRegistryGas.s.sol new file mode 100644 index 000000000..b452fd286 --- /dev/null +++ b/src/gas/registry/AddressRegistryGas.s.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec. +pragma solidity >=0.8.4; + +import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; +import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; + +import {AddressRegistryDeployment} from "../../deployment/registry/AddressRegistryDeployment.s.sol"; +import {GasBase} from "../base/GasBase.sol"; + +interface IRead { + function defiBridgeProxy() external view returns (address); +} + +contract AddressRegistryGas is AddressRegistryDeployment { + GasBase internal gasBase; + AddressRegistry internal bridge; + + function measure() public { + address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); + vm.label(defiProxy, "DefiProxy"); + + vm.broadcast(); + gasBase = new GasBase(defiProxy); + + address temp = ROLLUP_PROCESSOR; + ROLLUP_PROCESSOR = address(gasBase); + address bridge = deployAndList(); + ROLLUP_PROCESSOR = temp; + + AztecTypes.AztecAsset memory empty; + AztecTypes.AztecAsset memory eth = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + AztecTypes.AztecAsset memory virtualAsset = + AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + + vm.broadcast(); + address(gasBase).call{value: 2 ether}(""); + emit log_named_uint("Balance of ", address(gasBase).balance); + + // Get virtual assets + { + vm.broadcast(); + gasBase.convert(bridge, eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + } + + uint256 inputAmount = uint256(uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA)); + // register address + { + vm.broadcast(); + gasBase.convert(bridge, virtualAsset, empty, virtualAsset, empty, inputAmount, 0, 0, address(0), 400000); + } + } +} From aa7049eebfdc5981a20f62b9c27689625cb9ce94 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 7 Dec 2022 20:26:57 -0500 Subject: [PATCH 34/65] test deposit/withdraw events --- src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index 7cce8a8da..922acbabf 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -35,6 +35,9 @@ contract NftVaultBasicE2ETest is BridgeTestBase { AztecTypes.AztecAsset private erc20InputAsset = AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); + event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + function setUp() public { registry = new AddressRegistry(address(ROLLUP_PROCESSOR)); bridge = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); @@ -89,6 +92,9 @@ contract NftVaultBasicE2ETest is BridgeTestBase { assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); address collection = address(nftContract); + + vm.expectEmit(true, true, false, false); + emit NftDeposit(virtualAsset100.id, collection, tokenIdToDeposit); bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); @@ -98,6 +104,9 @@ contract NftVaultBasicE2ETest is BridgeTestBase { function testWithdraw() public { testDeposit(); uint64 auxData = registry.addressCount(); + + vm.expectEmit(true, true, false, false); + emit NftWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); From 746f595fc6ae46cc91ed75c12ae91e5792eb9178 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 10:46:10 -0500 Subject: [PATCH 35/65] fmt --- src/gas/nft-basic/NftVaultGas.s.sol | 14 ++++++++++++-- src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 5a41224b1..77c20bc84 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -13,7 +13,6 @@ import {GasBase} from "../base/GasBase.sol"; import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; - interface IRead { function defiBridgeProxy() external view returns (address); } @@ -56,7 +55,18 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { // get registry virtual asset gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); // register address - gasBase.convert(address(registry), virtualAsset, empty, virtualAsset, empty, uint256(uint160(addr1)), 0, 0, address(0), 400000); + gasBase.convert( + address(registry), + virtualAsset, + empty, + virtualAsset, + empty, + uint256(uint160(addr1)), + 0, + 0, + address(0), + 400000 + ); nftContract.approve(address(bridge), 0); vm.stopBroadcast(); diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index ec2f93f7f..20d72e382 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -130,7 +130,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.expectRevert(); bridge.convert( - ethAsset, // _inputAssetA + ethAsset, // _inputAssetA emptyAsset, // _inputAssetB virtualAsset100, // _outputAssetA emptyAsset, // _outputAssetB @@ -165,7 +165,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { testDeposit(); uint64 auxData = registry.addressCount(); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - virtualAsset100, // _inputAssetA + virtualAsset100, // _inputAssetA emptyAsset, // _inputAssetB ethAsset, // _outputAssetA emptyAsset, // _outputAssetB From 055c3996eaf2df000efb99423612ac08dd4f3054 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 11:09:22 -0500 Subject: [PATCH 36/65] natspec comments --- src/bridges/nft-basic/NftVault.sol | 34 +++++++++++++++++++++++- src/bridges/registry/AddressRegistry.sol | 25 ++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 1468c1b65..df27dbd10 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -10,7 +10,7 @@ import {AddressRegistry} from "../registry/AddressRegistry.sol"; /** * @title Basic NFT Vault for Aztec. - * @author Aztec Team + * @author Josh Crites, (@critesjosh on Github), Aztec Team * @notice You can use this contract to hold your NFTs on Aztec. Whoever holds the corresponding virutal asset note can withdraw the NFT. * @dev This bridge demonstrates basic functionality for an NFT bridge. This may be extended to support more features. */ @@ -26,10 +26,31 @@ contract NftVault is BridgeBase { event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + /** + * @notice Set the addresses of RollupProcessor.sol and AddressRegistry.sol + * @param _rollupProcessor Address of the RollupProcessor.sol + * @param _registry Address of the AddressRegistry.sol + */ constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { registry = AddressRegistry(_registry); } + /** + * @notice Function for the first step of a NFT deposit, or a NFT withdrawal. + * @dev This method can only be called from the RollupProcessor.sol. The first step of the + * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the + * virutal asset note is received on Aztec, the user calls matchDeposit which deposits the NFT + * into Aztec and matches it with the virtual asset. When the virutal asset is sent to this function + * it is burned and the NFT is sent to the user (withdraw). + * + * @param _inputAssetA - ETH (Deposit) or VIRTUAL (Withdrawal) + * @param _outputAssetA - VIRTUAL (Deposit) or 0 ETH (Withdrawal) + * @param _totalInputValue - must be 1 wei (Deposit) or 1 VIRTUAL (Withdrawal) + * @param _auxData - corresponds to the Ethereum address id in the AddressRegistry.sol for withdrawals + * @return outputValueA - 1 VIRTUAL asset (Deposit) or 0 ETH (Withdrawal) + * + */ + function convert( AztecTypes.AztecAsset calldata _inputAssetA, AztecTypes.AztecAsset calldata, @@ -81,6 +102,17 @@ contract NftVault is BridgeBase { } } + /** + * @notice Function for the second step of a NFT deposit. + * @dev This method is called by an Ethereum L1 account that owns the NFT to deposit. + * The user must approve this bridge contract to transfer the users NFT before this function + * is called. This function assumes the NFT contract complies with the ERC721 standard. + * + * @param _virtualAssetId - the virutal asset id of the note returned in the deposit step of the convert function + * @param _collection - collection address of the NFT + * @param _tokenId - the token id of the NFT + */ + function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { require(tokens[_virtualAssetId].collection == address(0x0), "Asset registered"); tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index af914f7ce..79bbecf77 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -8,7 +8,7 @@ import {BridgeBase} from "../base/BridgeBase.sol"; /** * @title Aztec Address Registry. - * @author Aztec Team + * @author Josh Crites (@critesjosh on Github), Aztec team * @notice This contract can be used to anonymously register an ethereum address with an id. * This is useful for reducing the amount of data required to pass an ethereum address through auxData. * @dev Use this contract to lookup ethereum addresses by id. @@ -25,6 +25,20 @@ contract AddressRegistry is BridgeBase { */ constructor(address _rollupProcessor) BridgeBase(_rollupProcessor) {} + /** + * @notice Function for getting VIRTUAL assets (step 1) to register an address and registering an address (step 2). + * @dev This method can only be called from the RollupProcessor.sol. The first step to register an address is for a user to + * get the type(uint160).max value of VIRTUAL assets back from the bridge. The second step is for the user + * to send an amount of VIRTUAL assets back to the bridge. The amount that is sent back is equal to number of the + * ethereum address that is being registered (e.g. uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEB)). + * + * @param _inputAssetA - ETH (step 1) or VIRTUAL (step 2) + * @param _outputAssetA - VIRTUAL (steps 1 and 2) + * @param _totalInputValue - must be 1 wei (ETH) (step 1) or address value (step 2) + * @return outputValueA - type(uint160).max (step 1) or 0 VIRTUAL (step 2) + * + */ + function convert( AztecTypes.AztecAsset calldata _inputAssetA, AztecTypes.AztecAsset calldata, @@ -62,6 +76,15 @@ contract AddressRegistry is BridgeBase { } } + /** + * @notice Function for registering an address from Ethereum. + * @dev This function can be called directly from another Ethereum account. This can be done in + * one step, in one transaction. Coming from Ethereum directly, this method is not as privacy + * preserving as registering an address through the bridge. + * + * @param _to - ETH (step 1) or VIRTUAL (step 2) + */ + function registerWithdrawAddress(address _to) external returns (uint256) { addressCount++; addresses[addressCount] = _to; From 41004f2a2b8f175f0d30d8bf0a9e824ecec61ea3 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 11:10:41 -0500 Subject: [PATCH 37/65] fmt --- src/bridges/nft-basic/NftVault.sol | 6 +++--- src/bridges/registry/AddressRegistry.sol | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index df27dbd10..59a1c94de 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -37,8 +37,8 @@ contract NftVault is BridgeBase { /** * @notice Function for the first step of a NFT deposit, or a NFT withdrawal. - * @dev This method can only be called from the RollupProcessor.sol. The first step of the - * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the + * @dev This method can only be called from the RollupProcessor.sol. The first step of the + * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the * virutal asset note is received on Aztec, the user calls matchDeposit which deposits the NFT * into Aztec and matches it with the virtual asset. When the virutal asset is sent to this function * it is burned and the NFT is sent to the user (withdraw). @@ -104,7 +104,7 @@ contract NftVault is BridgeBase { /** * @notice Function for the second step of a NFT deposit. - * @dev This method is called by an Ethereum L1 account that owns the NFT to deposit. + * @dev This method is called by an Ethereum L1 account that owns the NFT to deposit. * The user must approve this bridge contract to transfer the users NFT before this function * is called. This function assumes the NFT contract complies with the ERC721 standard. * diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 79bbecf77..52a6b1e96 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -28,7 +28,7 @@ contract AddressRegistry is BridgeBase { /** * @notice Function for getting VIRTUAL assets (step 1) to register an address and registering an address (step 2). * @dev This method can only be called from the RollupProcessor.sol. The first step to register an address is for a user to - * get the type(uint160).max value of VIRTUAL assets back from the bridge. The second step is for the user + * get the type(uint160).max value of VIRTUAL assets back from the bridge. The second step is for the user * to send an amount of VIRTUAL assets back to the bridge. The amount that is sent back is equal to number of the * ethereum address that is being registered (e.g. uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEB)). * @@ -81,7 +81,7 @@ contract AddressRegistry is BridgeBase { * @dev This function can be called directly from another Ethereum account. This can be done in * one step, in one transaction. Coming from Ethereum directly, this method is not as privacy * preserving as registering an address through the bridge. - * + * * @param _to - ETH (step 1) or VIRTUAL (step 2) */ From 623725efb9f7f725be04963120c5d7673183043e Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 11:43:57 -0500 Subject: [PATCH 38/65] add test --- src/test/bridges/registry/AddressRegistryUnitTest.t.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index 374870e5e..f188941ad 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -116,4 +116,11 @@ contract AddressRegistryUnitTest is BridgeTestBase { assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); } + + function testRegisterFromEth() public { + address to = address(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); + uint256 count = bridge.registerWithdrawAddress(to); + address registered = bridge.addresses(count); + assertEq(to, registered, "Address not registered"); + } } From 55031c99c299863a7c0a79dc64a99869cb48c588 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 12:20:36 -0500 Subject: [PATCH 39/65] fix linting --- src/bridges/base/ErrorLib.sol | 2 + src/bridges/nft-basic/NftVault.sol | 70 +++++++++++++------ src/bridges/registry/AddressRegistry.sol | 5 +- .../bridges/nft-basic/NftVaultBasicE2E.t.sol | 6 +- .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 8 +-- 5 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/bridges/base/ErrorLib.sol b/src/bridges/base/ErrorLib.sol index 369cd99f5..4015af04d 100644 --- a/src/bridges/base/ErrorLib.sol +++ b/src/bridges/base/ErrorLib.sol @@ -18,4 +18,6 @@ library ErrorLib { error InvalidNonce(); error AsyncDisabled(); + + error InvalidVirtualAsset(); } diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 59a1c94de..b5888b48a 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -21,18 +21,29 @@ contract NftVault is BridgeBase { } mapping(uint256 => NftAsset) public tokens; - AddressRegistry public immutable registry; + AddressRegistry public immutable REGISTRY; - event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); - event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NftDeposit( + uint256 indexed virtualAssetId, + address indexed collection, + uint256 indexed tokenId + ); + event NftWithdraw( + uint256 indexed virtualAssetId, + address indexed collection, + uint256 indexed tokenId + ); /** * @notice Set the addresses of RollupProcessor.sol and AddressRegistry.sol * @param _rollupProcessor Address of the RollupProcessor.sol * @param _registry Address of the AddressRegistry.sol */ - constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { - registry = AddressRegistry(_registry); + constructor( + address _rollupProcessor, + address _registry + ) BridgeBase(_rollupProcessor) { + REGISTRY = AddressRegistry(_registry); } /** @@ -63,7 +74,7 @@ contract NftVault is BridgeBase { ) external payable - override ( + override( // uint64 _auxData, // address _rollupBeneficiary BridgeBase @@ -72,30 +83,37 @@ contract NftVault is BridgeBase { returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED - || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || + _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); if ( - _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED - || _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || + _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidOutputA(); if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH - && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && + _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - require(_totalInputValue == 1, "send only 1 wei"); + if(_totalInputValue != 1 wei) + revert ErrorLib.InvalidInputAmount(); return (1, 0, false); } else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && + _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { NftAsset memory token = tokens[_inputAssetA.id]; - require(token.collection != address(0x0), "NFT doesn't exist"); + if (token.collection == address(0x0)) + revert ErrorLib.InvalidInputA(); - address _to = registry.addresses(_auxData); - require(_to != address(0x0), "unregistered withdraw address"); + address _to = REGISTRY.addresses(_auxData); + if(_to == address(0x0)) + revert ErrorLib.InvalidAuxData(); - IERC721(token.collection).transferFrom(address(this), _to, token.id); + IERC721(token.collection).transferFrom( + address(this), + _to, + token.id + ); emit NftWithdraw(_inputAssetA.id, token.collection, token.id); delete tokens[_inputAssetA.id]; return (0, 0, false); @@ -113,9 +131,17 @@ contract NftVault is BridgeBase { * @param _tokenId - the token id of the NFT */ - function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { - require(tokens[_virtualAssetId].collection == address(0x0), "Asset registered"); - tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); + function matchDeposit( + uint256 _virtualAssetId, + address _collection, + uint256 _tokenId + ) external { + if(tokens[_virtualAssetId].collection != address(0x0)) + revert ErrorLib.InvalidVirtualAsset(); + tokens[_virtualAssetId] = NftAsset({ + collection: _collection, + id: _tokenId + }); IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); emit NftDeposit(_virtualAssetId, _collection, _tokenId); } diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 52a6b1e96..77a1ec975 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -60,7 +60,8 @@ contract AddressRegistry is BridgeBase { _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - require(_totalInputValue == 1, "send only 1 wei"); + if(_totalInputValue != 1 wei) + revert ErrorLib.InvalidInputAmount(); return (type(uint160).max, 0, false); } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL @@ -72,7 +73,7 @@ contract AddressRegistry is BridgeBase { emit AddressRegistered(addressCount, toRegister); return (0, 0, false); } else { - revert("invalid input/output types"); + revert ErrorLib.InvalidInput(); } } diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index 922acbabf..ac9d639bd 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -25,7 +25,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { uint256 private id; uint256 private registryBridgeId; uint256 private tokenIdToDeposit = 1; - address private constant registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant REGISTER_ADDRESS = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; AztecTypes.AztecAsset private ethAsset; AztecTypes.AztecAsset private virtualAsset1 = @@ -74,7 +74,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { ROLLUP_ENCODER.processRollupAndGetBridgeResult(); // register an address - uint160 inputAmount = uint160(registeredAddress); + uint160 inputAmount = uint160(REGISTER_ADDRESS); ROLLUP_ENCODER.defiInteractionL2( registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount ); @@ -111,7 +111,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); address owner = nftContract.ownerOf(tokenIdToDeposit); - assertEq(registeredAddress, owner, "registered address is not the owner"); + assertEq(REGISTER_ADDRESS, owner, "registered address is not the owner"); assertEq(outputValueA, 0, "Output value A is not 0"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index 20d72e382..0da76b99b 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -25,7 +25,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { ERC721PresetMinterPauserAutoId private nftContract; uint256 private tokenIdToDeposit = 1; AddressRegistry private registry; - address private constant registeredAddress = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; + address private constant REGISTER_ADDRESS = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; AztecTypes.AztecAsset private ethAsset = @@ -37,8 +37,6 @@ contract NftVaultBasicUnitTest is BridgeTestBase { AztecTypes.AztecAsset private erc20InputAsset = AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); - event log(string, address); - // @dev This method exists on RollupProcessor.sol. It's defined here in order to be able to receive ETH like a real // rollup processor would. function receiveEthFromBridge(uint256 _interactionNonce) external payable {} @@ -69,7 +67,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { 0, // _auxData address(0x0) ); - uint256 inputAmount = uint160(address(registeredAddress)); + uint256 inputAmount = uint160(address(REGISTER_ADDRESS)); // register an address registry.convert( virtualAsset1, @@ -175,7 +173,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address(0) ); address owner = nftContract.ownerOf(tokenIdToDeposit); - assertEq(registeredAddress, owner, "registered address is not the owner"); + assertEq(REGISTER_ADDRESS, owner, "registered address is not the owner"); assertEq(outputValueA, 0, "Output value A is not 0"); assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); From 32214ebebe28158d74e704d331712487f48d5e9d Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 12:21:08 -0500 Subject: [PATCH 40/65] fmt --- src/bridges/nft-basic/NftVault.sol | 64 +++++++++--------------- src/bridges/registry/AddressRegistry.sol | 3 +- 2 files changed, 25 insertions(+), 42 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index b5888b48a..07a341849 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -23,26 +23,15 @@ contract NftVault is BridgeBase { mapping(uint256 => NftAsset) public tokens; AddressRegistry public immutable REGISTRY; - event NftDeposit( - uint256 indexed virtualAssetId, - address indexed collection, - uint256 indexed tokenId - ); - event NftWithdraw( - uint256 indexed virtualAssetId, - address indexed collection, - uint256 indexed tokenId - ); + event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); /** * @notice Set the addresses of RollupProcessor.sol and AddressRegistry.sol * @param _rollupProcessor Address of the RollupProcessor.sol * @param _registry Address of the AddressRegistry.sol */ - constructor( - address _rollupProcessor, - address _registry - ) BridgeBase(_rollupProcessor) { + constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { REGISTRY = AddressRegistry(_registry); } @@ -74,7 +63,7 @@ contract NftVault is BridgeBase { ) external payable - override( + override ( // uint64 _auxData, // address _rollupBeneficiary BridgeBase @@ -83,37 +72,36 @@ contract NftVault is BridgeBase { returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || - _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED + || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidInputA(); if ( - _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || - _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 + _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED + || _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidOutputA(); if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && - _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH + && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - if(_totalInputValue != 1 wei) + if (_totalInputValue != 1 wei) { revert ErrorLib.InvalidInputAmount(); + } return (1, 0, false); } else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && - _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { NftAsset memory token = tokens[_inputAssetA.id]; - if (token.collection == address(0x0)) + if (token.collection == address(0x0)) { revert ErrorLib.InvalidInputA(); + } address _to = REGISTRY.addresses(_auxData); - if(_to == address(0x0)) + if (_to == address(0x0)) { revert ErrorLib.InvalidAuxData(); + } - IERC721(token.collection).transferFrom( - address(this), - _to, - token.id - ); + IERC721(token.collection).transferFrom(address(this), _to, token.id); emit NftWithdraw(_inputAssetA.id, token.collection, token.id); delete tokens[_inputAssetA.id]; return (0, 0, false); @@ -131,17 +119,11 @@ contract NftVault is BridgeBase { * @param _tokenId - the token id of the NFT */ - function matchDeposit( - uint256 _virtualAssetId, - address _collection, - uint256 _tokenId - ) external { - if(tokens[_virtualAssetId].collection != address(0x0)) + function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { + if (tokens[_virtualAssetId].collection != address(0x0)) { revert ErrorLib.InvalidVirtualAsset(); - tokens[_virtualAssetId] = NftAsset({ - collection: _collection, - id: _tokenId - }); + } + tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); emit NftDeposit(_virtualAssetId, _collection, _tokenId); } diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 77a1ec975..398c44083 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -60,8 +60,9 @@ contract AddressRegistry is BridgeBase { _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - if(_totalInputValue != 1 wei) + if (_totalInputValue != 1 wei) { revert ErrorLib.InvalidInputAmount(); + } return (type(uint160).max, 0, false); } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL From ae3365187a241f205e7365843df8a29588751ee6 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 12:27:15 -0500 Subject: [PATCH 41/65] uint256 addressCount --- src/bridges/registry/AddressRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index 398c44083..efc407872 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -14,7 +14,7 @@ import {BridgeBase} from "../base/BridgeBase.sol"; * @dev Use this contract to lookup ethereum addresses by id. */ contract AddressRegistry is BridgeBase { - uint64 public addressCount; + uint256 public addressCount; mapping(uint256 => address) public addresses; event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); From a4dbf00a43746e3621f85250fd18d9e7893f9fbe Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 16:23:55 -0500 Subject: [PATCH 42/65] incorporate lasse's feedback --- src/bridges/base/ErrorLib.sol | 2 - src/bridges/nft-basic/NftVault.sol | 48 +++++++++---------- src/bridges/registry/AddressRegistry.sol | 37 ++++++-------- .../bridges/nft-basic/NftVaultBasicE2E.t.sol | 6 +-- .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 8 ++-- .../bridges/registry/AddressRegistryE2E.t.sol | 7 ++- .../registry/AddressRegistryUnitTest.t.sol | 6 +-- 7 files changed, 51 insertions(+), 63 deletions(-) diff --git a/src/bridges/base/ErrorLib.sol b/src/bridges/base/ErrorLib.sol index 4015af04d..369cd99f5 100644 --- a/src/bridges/base/ErrorLib.sol +++ b/src/bridges/base/ErrorLib.sol @@ -18,6 +18,4 @@ library ErrorLib { error InvalidNonce(); error AsyncDisabled(); - - error InvalidVirtualAsset(); } diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 07a341849..748e74d5c 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -17,19 +17,22 @@ import {AddressRegistry} from "../registry/AddressRegistry.sol"; contract NftVault is BridgeBase { struct NftAsset { address collection; - uint256 id; + uint256 tokenId; } - mapping(uint256 => NftAsset) public tokens; AddressRegistry public immutable REGISTRY; + mapping(uint256 => NftAsset) public nftAssets; + + error InvalidVirtualAssetId(); + event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); /** - * @notice Set the addresses of RollupProcessor.sol and AddressRegistry.sol - * @param _rollupProcessor Address of the RollupProcessor.sol - * @param _registry Address of the AddressRegistry.sol + * @notice Set the addresses of RollupProcessor and AddressRegistry + * @param _rollupProcessor Address of the RollupProcessor + * @param _registry Address of the AddressRegistry */ constructor(address _rollupProcessor, address _registry) BridgeBase(_rollupProcessor) { REGISTRY = AddressRegistry(_registry); @@ -37,11 +40,11 @@ contract NftVault is BridgeBase { /** * @notice Function for the first step of a NFT deposit, or a NFT withdrawal. - * @dev This method can only be called from the RollupProcessor.sol. The first step of the + * @dev This method can only be called from the RollupProcessor. The first step of the * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the * virutal asset note is received on Aztec, the user calls matchDeposit which deposits the NFT * into Aztec and matches it with the virtual asset. When the virutal asset is sent to this function - * it is burned and the NFT is sent to the user (withdraw). + * it is burned and the NFT is sent to the recipient passed in _auxData. * * @param _inputAssetA - ETH (Deposit) or VIRTUAL (Withdrawal) * @param _outputAssetA - VIRTUAL (Deposit) or 0 ETH (Withdrawal) @@ -63,11 +66,7 @@ contract NftVault is BridgeBase { ) external payable - override ( - // uint64 _auxData, - // address _rollupBeneficiary - BridgeBase - ) + override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { @@ -79,31 +78,30 @@ contract NftVault is BridgeBase { _outputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || _outputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 ) revert ErrorLib.InvalidOutputA(); + if (_totalInputValue != 1) { + revert ErrorLib.InvalidInputAmount(); + } if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { - if (_totalInputValue != 1 wei) { - revert ErrorLib.InvalidInputAmount(); - } return (1, 0, false); } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { - NftAsset memory token = tokens[_inputAssetA.id]; + NftAsset memory token = nftAssets[_inputAssetA.id]; if (token.collection == address(0x0)) { revert ErrorLib.InvalidInputA(); } - address _to = REGISTRY.addresses(_auxData); - if (_to == address(0x0)) { + address to = REGISTRY.addresses(_auxData); + if (to == address(0x0)) { revert ErrorLib.InvalidAuxData(); } - - IERC721(token.collection).transferFrom(address(this), _to, token.id); - emit NftWithdraw(_inputAssetA.id, token.collection, token.id); - delete tokens[_inputAssetA.id]; + delete nftAssets[_inputAssetA.id]; + IERC721(token.collection).transferFrom(address(this), to, token.tokenId); + emit NftWithdraw(_inputAssetA.id, token.collection, token.tokenId); return (0, 0, false); } } @@ -120,10 +118,10 @@ contract NftVault is BridgeBase { */ function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { - if (tokens[_virtualAssetId].collection != address(0x0)) { - revert ErrorLib.InvalidVirtualAsset(); + if (nftAssets[_virtualAssetId].collection != address(0x0)) { + revert InvalidVirtualAssetId(); } - tokens[_virtualAssetId] = NftAsset({collection: _collection, id: _tokenId}); + nftAssets[_virtualAssetId] = NftAsset({collection: _collection, tokenId: _tokenId}); IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); emit NftDeposit(_virtualAssetId, _collection, _tokenId); } diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index efc407872..a9f0a8651 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -17,7 +17,7 @@ contract AddressRegistry is BridgeBase { uint256 public addressCount; mapping(uint256 => address) public addresses; - event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); + event AddressRegistered(uint256 indexed index, address indexed entity); /** * @notice Set address of rollup processor @@ -27,9 +27,9 @@ contract AddressRegistry is BridgeBase { /** * @notice Function for getting VIRTUAL assets (step 1) to register an address and registering an address (step 2). - * @dev This method can only be called from the RollupProcessor.sol. The first step to register an address is for a user to + * @dev This method can only be called from the RollupProcessor. The first step to register an address is for a user to * get the type(uint160).max value of VIRTUAL assets back from the bridge. The second step is for the user - * to send an amount of VIRTUAL assets back to the bridge. The amount that is sent back is equal to number of the + * to send an amount of VIRTUAL assets back to the bridge. The amount that is sent back is equal to the number of the * ethereum address that is being registered (e.g. uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEB)). * * @param _inputAssetA - ETH (step 1) or VIRTUAL (step 2) @@ -56,22 +56,14 @@ contract AddressRegistry is BridgeBase { if (_outputAssetA.assetType != AztecTypes.AztecAssetType.VIRTUAL) { revert ErrorLib.InvalidOutputA(); } - if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH - && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - ) { - if (_totalInputValue != 1 wei) { + if (_inputAssetA.assetType == AztecTypes.AztecAssetType.ETH) { + if (_totalInputValue != 1) { revert ErrorLib.InvalidInputAmount(); } return (type(uint160).max, 0, false); - } else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - ) { - addressCount++; + } else if (_inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL) { address toRegister = address(uint160(_totalInputValue)); - addresses[addressCount] = toRegister; - emit AddressRegistered(addressCount, toRegister); + registerAddress(toRegister); return (0, 0, false); } else { revert ErrorLib.InvalidInput(); @@ -79,18 +71,19 @@ contract AddressRegistry is BridgeBase { } /** - * @notice Function for registering an address from Ethereum. + * @notice Register an address at the registry * @dev This function can be called directly from another Ethereum account. This can be done in * one step, in one transaction. Coming from Ethereum directly, this method is not as privacy * preserving as registering an address through the bridge. * - * @param _to - ETH (step 1) or VIRTUAL (step 2) + * @param _to - The address to register + * @return addressCount - the index of address that has been registered */ - function registerWithdrawAddress(address _to) external returns (uint256) { - addressCount++; - addresses[addressCount] = _to; - emit AddressRegistered(addressCount, _to); - return addressCount; + function registerAddress(address _to) public returns (uint256) { + uint256 userIndex = addressCount++; + addresses[userIndex] = _to; + emit AddressRegistered(userIndex, _to); + return userIndex; } } diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index ac9d639bd..cb2e4ac12 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -96,14 +96,14 @@ contract NftVaultBasicE2ETest is BridgeTestBase { vm.expectEmit(true, true, false, false); emit NftDeposit(virtualAsset100.id, collection, tokenIdToDeposit); bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); - (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); + (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); } function testWithdraw() public { testDeposit(); - uint64 auxData = registry.addressCount(); + uint64 auxData = uint64(registry.addressCount()); vm.expectEmit(true, true, false, false); emit NftWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); @@ -116,7 +116,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - (address _a, uint256 _id) = bridge.tokens(virtualAsset100.id); + (address _a, uint256 _id) = bridge.nftAssets(virtualAsset100.id); assertEq(_a, address(0), "collection address is not 0"); assertEq(_id, 0, "token id is not 0"); } diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index 0da76b99b..a002d5a1d 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -144,7 +144,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address collection = address(nftContract); bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); - (address returnedCollection, uint256 returnedId) = bridge.tokens(virtualAsset100.id); + (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); } @@ -161,7 +161,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { function testWithdraw() public { testDeposit(); - uint64 auxData = registry.addressCount(); + uint64 auxData = uint64(registry.addressCount()-1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( virtualAsset100, // _inputAssetA emptyAsset, // _inputAssetB @@ -178,7 +178,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { assertEq(outputValueB, 0, "Output value B is not 0"); assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); - (address _a, uint256 _id) = bridge.tokens(virtualAsset100.id); + (address _a, uint256 _id) = bridge.nftAssets(virtualAsset100.id); assertEq(_a, address(0), "collection address is not 0"); assertEq(_id, 0, "token id is not 0"); } @@ -186,7 +186,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { // should fail because no NFT has been registered with this virtual asset function testWithdrawUnregisteredNft() public { testDeposit(); - uint64 auxData = registry.addressCount(); + uint64 auxData = uint64(registry.addressCount()); vm.expectRevert(); bridge.convert( virtualAsset1, // _inputAssetA diff --git a/src/test/bridges/registry/AddressRegistryE2E.t.sol b/src/test/bridges/registry/AddressRegistryE2E.t.sol index c59d2ac28..2191ac198 100644 --- a/src/test/bridges/registry/AddressRegistryE2E.t.sol +++ b/src/test/bridges/registry/AddressRegistryE2E.t.sol @@ -59,15 +59,14 @@ contract AddressRegistryE2ETest is BridgeTestBase { uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); vm.expectEmit(true, true, false, false); - emit AddressRegistered(1, address(inputAmount)); + emit AddressRegistered(0, address(inputAmount)); ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - uint64 addressId = bridge.addressCount(); - uint64 registeredId = addressId; - address newlyRegistered = bridge.addresses(registeredId); + uint64 addressId = uint64(bridge.addressCount()) - 1; + address newlyRegistered = bridge.addresses(addressId); assertEq(address(inputAmount), newlyRegistered, "input amount doesn't equal newly registered address"); assertEq(outputValueA, 0, "Non-zero outputValueA"); diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index f188941ad..ba71e3a23 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -95,7 +95,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); vm.expectEmit(true, true, false, false); - emit AddressRegistered(1, address(inputAmount)); + emit AddressRegistered(0, address(inputAmount)); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( inputAssetA, @@ -108,7 +108,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { address(0x0) ); - uint256 id = bridge.addressCount(); + uint256 id = bridge.addressCount() - 1; address newlyRegistered = bridge.addresses(id); assertEq(address(inputAmount), newlyRegistered, "Address not registered"); @@ -119,7 +119,7 @@ contract AddressRegistryUnitTest is BridgeTestBase { function testRegisterFromEth() public { address to = address(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); - uint256 count = bridge.registerWithdrawAddress(to); + uint256 count = bridge.registerAddress(to); address registered = bridge.addresses(count); assertEq(to, registered, "Address not registered"); } From d0b3cefae214e554f3641ca0c11b8f7138740965 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 20:13:09 -0500 Subject: [PATCH 43/65] fix test --- src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index cb2e4ac12..28842ced7 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -103,7 +103,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { function testWithdraw() public { testDeposit(); - uint64 auxData = uint64(registry.addressCount()); + uint64 auxData = uint64(registry.addressCount() - 1); vm.expectEmit(true, true, false, false); emit NftWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); From 8367e39977581b5be1bb17da7d25acb55f49724c Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 8 Dec 2022 20:14:46 -0500 Subject: [PATCH 44/65] fmt --- src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index a002d5a1d..4ed67f694 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -161,7 +161,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { function testWithdraw() public { testDeposit(); - uint64 auxData = uint64(registry.addressCount()-1); + uint64 auxData = uint64(registry.addressCount() - 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( virtualAsset100, // _inputAssetA emptyAsset, // _inputAssetB From b6e18ea3a0fd721902ff9ebc70b442c4446a75ff Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 23 Dec 2022 20:33:26 -0500 Subject: [PATCH 45/65] add transfer functionality --- src/bridges/nft-basic/NftVault.sol | 31 +++++-- src/gas/nft-basic/NftVaultGas.s.sol | 62 +++++++++---- .../bridges/nft-basic/NftVaultBasicE2E.t.sol | 47 ++++++++-- .../bridges/nft-basic/NftVaultBasicUnit.t.sol | 90 +++++++++++++------ 4 files changed, 173 insertions(+), 57 deletions(-) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NftVault.sol index 748e74d5c..46b27a81b 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NftVault.sol @@ -39,16 +39,18 @@ contract NftVault is BridgeBase { } /** - * @notice Function for the first step of a NFT deposit, or a NFT withdrawal. + * @notice Function for the first step of a NFT deposit, a NFT withdrawal, or transfer to another NftVault. * @dev This method can only be called from the RollupProcessor. The first step of the * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the - * virutal asset note is received on Aztec, the user calls matchDeposit which deposits the NFT + * virutal asset note is received on Aztec, the user calls transferFromAndMatch which deposits the NFT * into Aztec and matches it with the virtual asset. When the virutal asset is sent to this function * it is burned and the NFT is sent to the recipient passed in _auxData. * * @param _inputAssetA - ETH (Deposit) or VIRTUAL (Withdrawal) * @param _outputAssetA - VIRTUAL (Deposit) or 0 ETH (Withdrawal) * @param _totalInputValue - must be 1 wei (Deposit) or 1 VIRTUAL (Withdrawal) + * @param _interactionNonce - A globally unique identifier of this interaction/`convert(...)` call + * corresponding to the returned virtual asset id * @param _auxData - corresponds to the Ethereum address id in the AddressRegistry.sol for withdrawals * @return outputValueA - 1 VIRTUAL asset (Deposit) or 0 ETH (Withdrawal) * @@ -60,7 +62,7 @@ contract NftVault is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint256 _totalInputValue, - uint256, + uint256 _interactionNonce, uint64 _auxData, address ) @@ -103,21 +105,38 @@ contract NftVault is BridgeBase { IERC721(token.collection).transferFrom(address(this), to, token.tokenId); emit NftWithdraw(_inputAssetA.id, token.collection, token.tokenId); return (0, 0, false); + } else if ( + _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL + ) { + NftAsset memory token = nftAssets[_inputAssetA.id]; + if (token.collection == address(0x0)) { + revert ErrorLib.InvalidInputA(); + } + + address to = REGISTRY.addresses(_auxData); + delete nftAssets[_inputAssetA.id]; + + IERC721(token.collection).approve(to, token.tokenId); + NftVault(to).transferFromAndMatch(_interactionNonce, token.collection, token.tokenId); + + return (1, 0, false); } } /** - * @notice Function for the second step of a NFT deposit. - * @dev This method is called by an Ethereum L1 account that owns the NFT to deposit. + * @notice Function for the second step of a NFT deposit or for transfers from other NftVaults. + * @dev For a deposit, this method is called by an Ethereum L1 account that owns the NFT to deposit. * The user must approve this bridge contract to transfer the users NFT before this function * is called. This function assumes the NFT contract complies with the ERC721 standard. + * For a transfer from another NftVault, this method is called by the NftVault that is sending the NFT. * * @param _virtualAssetId - the virutal asset id of the note returned in the deposit step of the convert function * @param _collection - collection address of the NFT * @param _tokenId - the token id of the NFT */ - function matchDeposit(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { + function transferFromAndMatch(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { if (nftAssets[_virtualAssetId].collection != address(0x0)) { revert InvalidVirtualAssetId(); } diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 77c20bc84..73dc1b558 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -41,6 +41,7 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { ROLLUP_PROCESSOR = address(gasBase); registry = deployAndListAddressRegistry(); address bridge = deployAndList(registry); + address bridge2 = deployAndList(registry); ROLLUP_PROCESSOR = temp; AztecTypes.AztecAsset memory empty; @@ -48,25 +49,29 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); AztecTypes.AztecAsset memory virtualAsset = AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + AztecTypes.AztecAsset memory virtualAsset128 = + AztecTypes.AztecAsset({id: 128, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); vm.startBroadcast(); address(gasBase).call{value: 2 ether}(""); - // get registry virtual asset - gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); - // register address - gasBase.convert( - address(registry), - virtualAsset, - empty, - virtualAsset, - empty, - uint256(uint160(addr1)), - 0, - 0, - address(0), - 400000 - ); + _registerAddress(addr1); + _registerAddress(bridge2); + // // get registry virtual asset + // gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + // // register address + // gasBase.convert( + // address(registry), + // virtualAsset, + // empty, + // virtualAsset, + // empty, + // uint256(uint160(addr1)), + // 0, + // 0, + // address(0), + // 400000 + // ); nftContract.approve(address(bridge), 0); vm.stopBroadcast(); @@ -78,12 +83,35 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { // deposit nft { vm.broadcast(); - NftVault(bridge).matchDeposit(virtualAsset.id, address(nftContract), 0); + NftVault(bridge).transferFromAndMatch(virtualAsset.id, address(nftContract), 0); + } + // transfer nft + { + vm.broadcast(); + gasBase.convert(bridge, virtualAsset, empty, virtualAsset, empty, 1, 128, 2, address(0), 400000); } // withdraw nft { vm.broadcast(); - gasBase.convert(bridge, virtualAsset, empty, eth, empty, 1, 0, 1, address(0), 400000); + gasBase.convert(bridge2, virtualAsset128, empty, eth, empty, 1, 0, 1, address(0), 400000); } } + + function _registerAddress(address _toRegister) internal { + // get registry virtual asset + gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + // register address + gasBase.convert( + address(registry), + virtualAsset, + empty, + virtualAsset, + empty, + uint256(uint160(_toRegister)), + 0, + 0, + address(0), + 400000 + ); + } } diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index 28842ced7..9cb20b1d6 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -18,11 +18,13 @@ import {ERC721PresetMinterPauserAutoId} from */ contract NftVaultBasicE2ETest is BridgeTestBase { NftVault internal bridge; + NftVault internal bridge2; AddressRegistry private registry; ERC721PresetMinterPauserAutoId private nftContract; // To store the id of the bridge after being added - uint256 private id; + uint256 private bridgeId; + uint256 private bridge2Id; uint256 private registryBridgeId; uint256 private tokenIdToDeposit = 1; address private constant REGISTER_ADDRESS = 0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA; @@ -41,6 +43,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { function setUp() public { registry = new AddressRegistry(address(ROLLUP_PROCESSOR)); bridge = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); + bridge2 = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); nftContract.mint(address(this)); @@ -62,16 +65,20 @@ contract NftVaultBasicE2ETest is BridgeTestBase { // OTOH if you se it too high bridge users will pay too much ROLLUP_PROCESSOR.setSupportedBridge(address(registry), 120000); ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge2), 120000); vm.stopPrank(); // Fetch the id of the bridges - registryBridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 1; - id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); - + registryBridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 2; + bridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 1; + bridge2Id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); // get virutal assets to register an address ROLLUP_ENCODER.defiInteractionL2(registryBridgeId, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + // get virutal assets to register 2nd NftVault + ROLLUP_ENCODER.defiInteractionL2(registryBridgeId, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); + ROLLUP_ENCODER.processRollupAndGetBridgeResult(); // register an address uint160 inputAmount = uint160(REGISTER_ADDRESS); @@ -79,11 +86,17 @@ contract NftVaultBasicE2ETest is BridgeTestBase { registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount ); ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // register 2nd NftVault in AddressRegistry + uint160 bridge2AddressAmount = uint160(address(bridge2)); + ROLLUP_ENCODER.defiInteractionL2( + registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, bridge2AddressAmount + ); } function testDeposit() public { // get virtual asset before deposit - ROLLUP_ENCODER.defiInteractionL2(id, ethAsset, emptyAsset, virtualAsset100, emptyAsset, 0, 1); + ROLLUP_ENCODER.defiInteractionL2(bridgeId, ethAsset, emptyAsset, virtualAsset100, emptyAsset, 0, 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); @@ -95,7 +108,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { vm.expectEmit(true, true, false, false); emit NftDeposit(virtualAsset100.id, collection, tokenIdToDeposit); - bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -103,11 +116,11 @@ contract NftVaultBasicE2ETest is BridgeTestBase { function testWithdraw() public { testDeposit(); - uint64 auxData = uint64(registry.addressCount() - 1); + uint64 auxData = uint64(registry.addressCount() - 2); vm.expectEmit(true, true, false, false); emit NftWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); - ROLLUP_ENCODER.defiInteractionL2(id, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); + ROLLUP_ENCODER.defiInteractionL2(bridgeId, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); address owner = nftContract.ownerOf(tokenIdToDeposit); @@ -120,4 +133,22 @@ contract NftVaultBasicE2ETest is BridgeTestBase { assertEq(_a, address(0), "collection address is not 0"); assertEq(_id, 0, "token id is not 0"); } + + function testTransfer() public { + testDeposit(); + (address collection, uint256 tokenId) = bridge.nftAssets(virtualAsset100.id); + uint64 auxData = uint64(registry.addressCount() - 1); + + vm.expectEmit(true, true, false, false); + // ran test and determined the interaction nonce of the tx will be 128 + emit NftDeposit(128, collection, tokenId); + ROLLUP_ENCODER.defiInteractionL2(bridgeId, virtualAsset100, emptyAsset, virtualAsset1, emptyAsset, auxData, 1); + + ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + + // check that the nft was transferred to the second NftVault + (address returnedCollection, uint256 returnedId) = bridge2.nftAssets(128); + assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); + assertEq(returnedCollection, collection, "collection data does not match"); + } } diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol index 4ed67f694..d6cc55694 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol @@ -22,6 +22,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address private rollupProcessor; NftVault private bridge; + NftVault private bridge2; ERC721PresetMinterPauserAutoId private nftContract; uint256 private tokenIdToDeposit = 1; AddressRegistry private registry; @@ -47,6 +48,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { registry = new AddressRegistry(rollupProcessor); bridge = new NftVault(rollupProcessor, address(registry)); + bridge2 = new NftVault(rollupProcessor, address(registry)); nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); nftContract.mint(address(this)); @@ -56,29 +58,8 @@ contract NftVaultBasicUnitTest is BridgeTestBase { nftContract.approve(address(bridge), 1); nftContract.approve(address(bridge), 2); - // get virtual assets - registry.convert( - ethAsset, - emptyAsset, - virtualAsset1, - emptyAsset, - 1, // _totalInputValue - 0, // _interactionNonce - 0, // _auxData - address(0x0) - ); - uint256 inputAmount = uint160(address(REGISTER_ADDRESS)); - // register an address - registry.convert( - virtualAsset1, - emptyAsset, - virtualAsset1, - emptyAsset, - inputAmount, - 0, // _interactionNonce - 0, // _auxData - address(0x0) - ); + _registerAddress(REGISTER_ADDRESS); + _registerAddress(address(bridge2)); // Set ETH balance of bridge to 0 for clarity (somebody sent ETH to that address on mainnet) vm.deal(address(bridge), 0); @@ -143,7 +124,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.warp(block.timestamp + 1 days); address collection = address(nftContract); - bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -156,12 +137,12 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address collection = address(nftContract); vm.expectRevert(); - bridge.matchDeposit(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); } function testWithdraw() public { testDeposit(); - uint64 auxData = uint64(registry.addressCount() - 1); + uint64 auxData = uint64(registry.addressCount() - 2); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( virtualAsset100, // _inputAssetA emptyAsset, // _inputAssetB @@ -216,4 +197,61 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address(0) ); } + + function testTransfer() public { + testDeposit(); + uint64 auxData = uint64(registry.addressCount() - 1); + uint256 interactionNonce = 128; + + (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( + virtualAsset100, // _inputAssetA + emptyAsset, // _inputAssetB + virtualAsset100, // _outputAssetA + emptyAsset, // _outputAssetB + 1, // _totalInputValue + interactionNonce, // _interactionNonce + auxData, // _auxData + address(0) + ); + address owner = nftContract.ownerOf(tokenIdToDeposit); + assertEq(address(bridge2), owner, "registered address is not the owner"); + assertEq(outputValueA, 1, "Output value A is not 1"); + assertEq(outputValueB, 0, "Output value B is not 0"); + assertTrue(!isAsync, "Bridge is incorrectly in an async mode"); + + // test that the nft was deleted from bridge 1 + (address bridge1collection,) = bridge.nftAssets(virtualAsset100.id); + assertEq(bridge1collection, address(0), "collection was not deleted"); + + // test that the nft was added to bridge 2 + (address _a, uint256 _id) = bridge2.nftAssets(interactionNonce); + assertEq(_a, address(nftContract), "collection address is not 0"); + assertEq(_id, tokenIdToDeposit, "token id is not 0"); + } + + function _registerAddress(address _addressToRegister) internal { + // get virtual assets + registry.convert( + ethAsset, + emptyAsset, + virtualAsset1, + emptyAsset, + 1, // _totalInputValue + 0, // _interactionNonce + 0, // _auxData + address(0x0) + ); + uint256 inputAmount = uint160(address(_addressToRegister)); + // register an address + registry.convert( + virtualAsset1, + emptyAsset, + virtualAsset1, + emptyAsset, + inputAmount, + 0, // _interactionNonce + 0, // _auxData + address(0x0) + ); + } } From 249a9176fdcc12f5044057b721ac28c9a7d432bb Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 11:30:02 -0500 Subject: [PATCH 46/65] move asset defs to storage --- src/gas/nft-basic/NftVaultGas.s.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 73dc1b558..a61af315a 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -24,6 +24,14 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { address internal registry; uint256 internal registryAddressId; + AztecTypes.AztecAsset private empty; + AztecTypes.AztecAsset private eth = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + AztecTypes.AztecAsset private virtualAsset = + AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + AztecTypes.AztecAsset private virtualAsset128 = + AztecTypes.AztecAsset({id: 128, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + function measure() public { uint256 privKey1 = vm.envUint("PRIVATE_KEY"); address addr1 = vm.addr(privKey1); @@ -44,14 +52,6 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { address bridge2 = deployAndList(registry); ROLLUP_PROCESSOR = temp; - AztecTypes.AztecAsset memory empty; - AztecTypes.AztecAsset memory eth = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); - AztecTypes.AztecAsset memory virtualAsset = - AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - AztecTypes.AztecAsset memory virtualAsset128 = - AztecTypes.AztecAsset({id: 128, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - vm.startBroadcast(); address(gasBase).call{value: 2 ether}(""); From 55f306451e76297092cf4383ecbfdca3bde19bf2 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:03:36 -0500 Subject: [PATCH 47/65] add .env --- .env | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 000000000..24f97640e --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +network=mainnet +simulateAdmin=true \ No newline at end of file From 82f7617b7a718ba89cbb3fa545ab157087af3028 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:03:55 -0500 Subject: [PATCH 48/65] edits --- src/deployment/nft-basic/NftVaultDeployment.s.sol | 7 +++++-- src/gas/nft-basic/NftVaultGas.s.sol | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/deployment/nft-basic/NftVaultDeployment.s.sol b/src/deployment/nft-basic/NftVaultDeployment.s.sol index 0a6d0eda1..5877a5c14 100644 --- a/src/deployment/nft-basic/NftVaultDeployment.s.sol +++ b/src/deployment/nft-basic/NftVaultDeployment.s.sol @@ -30,10 +30,13 @@ contract NftVaultDeployment is BaseDeployment { function deployAndListAddressRegistry() public returns (address) { emit log("Deploying AddressRegistry bridge"); - vm.broadcast(); AddressRegistry bridge = new AddressRegistry(ROLLUP_PROCESSOR); - emit log_named_address("AddressRegistry bridge deployed to", address(bridge)); + emit log_named_address( + "AddressRegistry bridge deployed to", + address(bridge) + ); + uint256 addressId = listBridge(address(bridge), 400000); emit log_named_uint("AddressRegistry bridge address id", addressId); diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index a61af315a..0a7c9435a 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -17,9 +17,10 @@ interface IRead { function defiBridgeProxy() external view returns (address); } -contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { +contract NftVaultGas is NftVaultDeployment { GasBase internal gasBase; - NftVault internal bridge; + // NftVault internal bridge; + // NftVault internal bridge2; ERC721PresetMinterPauserAutoId internal nftContract; address internal registry; uint256 internal registryAddressId; @@ -56,6 +57,7 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { address(gasBase).call{value: 2 ether}(""); _registerAddress(addr1); + _registerAddress(bridge); _registerAddress(bridge2); // // get registry virtual asset // gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); @@ -73,6 +75,7 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { // 400000 // ); nftContract.approve(address(bridge), 0); + nftContract.approve(address(bridge2), 0); vm.stopBroadcast(); // Get virtual assets From 700255647d02d497dea27b4440a8d39aed2e0ecb Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:04:24 -0500 Subject: [PATCH 49/65] add .env --- .env | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 000000000..e69de29bb From 22588abd11e4116ed446fa1b081f21f78d39c6a9 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:39:20 -0500 Subject: [PATCH 50/65] add .env --- .env | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.env b/.env index e69de29bb..8dab26b54 100644 --- a/.env +++ b/.env @@ -0,0 +1,3 @@ +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +network=mainnet +simulateAdmin=false \ No newline at end of file From 4e937c840355f59d5add8eeb94fb517153a8c628 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:43:03 -0500 Subject: [PATCH 51/65] add readme --- src/gas/nft-basic/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/gas/nft-basic/README.md diff --git a/src/gas/nft-basic/README.md b/src/gas/nft-basic/README.md new file mode 100644 index 000000000..ae5333d3c --- /dev/null +++ b/src/gas/nft-basic/README.md @@ -0,0 +1,16 @@ +# how to run this + +1. create an .env file +``` +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +network=mainnet +simulateAdmin=false +``` +2. start anvil +``` +anvil --fork-url https://mainnet.infura.io/v3/${API_KEY} +``` +3. run this command +``` +forge script src/gas/nft-basic/NftVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` \ No newline at end of file From 77413642ac1f9b9b6fe88cf78cd52c1a4e11b935 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:48:52 -0500 Subject: [PATCH 52/65] update address id --- src/gas/nft-basic/NftVaultGas.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 77c20bc84..860f21789 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -83,7 +83,7 @@ contract NftVaultGas is NftVaultDeployment, AddressRegistryDeployment { // withdraw nft { vm.broadcast(); - gasBase.convert(bridge, virtualAsset, empty, eth, empty, 1, 0, 1, address(0), 400000); + gasBase.convert(bridge, virtualAsset, empty, eth, empty, 1, 0, 0, address(0), 400000); } } } From 73124ef3e6921b2e459791aa0a9d0710179531fc Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:49:38 -0500 Subject: [PATCH 53/65] add readme --- src/gas/nft-basic/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/gas/nft-basic/README.md diff --git a/src/gas/nft-basic/README.md b/src/gas/nft-basic/README.md new file mode 100644 index 000000000..e69de29bb From f6d875707211580f63f7a981b54742bdfc81b876 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 12:50:05 -0500 Subject: [PATCH 54/65] add content --- src/gas/nft-basic/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/gas/nft-basic/README.md b/src/gas/nft-basic/README.md index e69de29bb..ae5333d3c 100644 --- a/src/gas/nft-basic/README.md +++ b/src/gas/nft-basic/README.md @@ -0,0 +1,16 @@ +# how to run this + +1. create an .env file +``` +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +network=mainnet +simulateAdmin=false +``` +2. start anvil +``` +anvil --fork-url https://mainnet.infura.io/v3/${API_KEY} +``` +3. run this command +``` +forge script src/gas/nft-basic/NftVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` \ No newline at end of file From 4f91cf8782bf3f9fc5721b589a7afd206cb85172 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 13:15:28 -0500 Subject: [PATCH 55/65] update --- .env | 2 +- src/gas/nft-basic/NftVaultGas.s.sol | 25 ++++++------------------- src/gas/nft-basic/README.md | 2 +- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/.env b/.env index 24f97640e..8dab26b54 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 network=mainnet -simulateAdmin=true \ No newline at end of file +simulateAdmin=false \ No newline at end of file diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 0a7c9435a..368551764 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -54,28 +54,13 @@ contract NftVaultGas is NftVaultDeployment { ROLLUP_PROCESSOR = temp; vm.startBroadcast(); - address(gasBase).call{value: 2 ether}(""); + address(gasBase).call{value: 4 ether}(""); _registerAddress(addr1); _registerAddress(bridge); _registerAddress(bridge2); - // // get registry virtual asset - // gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); - // // register address - // gasBase.convert( - // address(registry), - // virtualAsset, - // empty, - // virtualAsset, - // empty, - // uint256(uint160(addr1)), - // 0, - // 0, - // address(0), - // 400000 - // ); + nftContract.approve(address(bridge), 0); - nftContract.approve(address(bridge2), 0); vm.stopBroadcast(); // Get virtual assets @@ -90,13 +75,15 @@ contract NftVaultGas is NftVaultDeployment { } // transfer nft { + address a = nftContract.ownerOf(0); + emit log_named_address("owner nft:", a); vm.broadcast(); - gasBase.convert(bridge, virtualAsset, empty, virtualAsset, empty, 1, 128, 2, address(0), 400000); + gasBase.convert(bridge, virtualAsset, empty, virtualAsset128, empty, 1, 128, 2, address(0), 400000); } // withdraw nft { vm.broadcast(); - gasBase.convert(bridge2, virtualAsset128, empty, eth, empty, 1, 0, 1, address(0), 400000); + gasBase.convert(bridge2, virtualAsset128, empty, eth, empty, 1, 0, 0, address(0), 400000); } } diff --git a/src/gas/nft-basic/README.md b/src/gas/nft-basic/README.md index ae5333d3c..ef7d577da 100644 --- a/src/gas/nft-basic/README.md +++ b/src/gas/nft-basic/README.md @@ -12,5 +12,5 @@ anvil --fork-url https://mainnet.infura.io/v3/${API_KEY} ``` 3. run this command ``` -forge script src/gas/nft-basic/NftVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +forge script src/gas/nft-basic/NftVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -vvvv ``` \ No newline at end of file From 62f2f204abfdc89085ff9060e0403d9ab1192de2 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Sat, 31 Dec 2022 14:02:42 -0500 Subject: [PATCH 56/65] fmt, lint --- src/deployment/nft-basic/NftVaultDeployment.s.sol | 5 +---- src/gas/nft-basic/NftVaultGas.s.sol | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/deployment/nft-basic/NftVaultDeployment.s.sol b/src/deployment/nft-basic/NftVaultDeployment.s.sol index 5877a5c14..2af23aa2f 100644 --- a/src/deployment/nft-basic/NftVaultDeployment.s.sol +++ b/src/deployment/nft-basic/NftVaultDeployment.s.sol @@ -32,10 +32,7 @@ contract NftVaultDeployment is BaseDeployment { AddressRegistry bridge = new AddressRegistry(ROLLUP_PROCESSOR); - emit log_named_address( - "AddressRegistry bridge deployed to", - address(bridge) - ); + emit log_named_address("AddressRegistry bridge deployed to", address(bridge)); uint256 addressId = listBridge(address(bridge), 400000); emit log_named_uint("AddressRegistry bridge address id", addressId); diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NftVaultGas.s.sol index 368551764..48c9f9d5d 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NftVaultGas.s.sol @@ -19,8 +19,8 @@ interface IRead { contract NftVaultGas is NftVaultDeployment { GasBase internal gasBase; - // NftVault internal bridge; - // NftVault internal bridge2; + NftVault internal bridge; + NftVault internal bridge2; ERC721PresetMinterPauserAutoId internal nftContract; address internal registry; uint256 internal registryAddressId; @@ -75,8 +75,6 @@ contract NftVaultGas is NftVaultDeployment { } // transfer nft { - address a = nftContract.ownerOf(0); - emit log_named_address("owner nft:", a); vm.broadcast(); gasBase.convert(bridge, virtualAsset, empty, virtualAsset128, empty, 1, 128, 2, address(0), 400000); } From e00d03d533591a5fdbc8d914f40ccdc6161101b9 Mon Sep 17 00:00:00 2001 From: josh c Date: Tue, 3 Jan 2023 09:20:03 -0500 Subject: [PATCH 57/65] Update .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4b6e85fbc..b8da22489 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ out/ node_modules/ yarn-error.log typechain-types/ -broadcast/ \ No newline at end of file +broadcast/ +.env From 5420aed54a55c1fcf1e17ea23df832a8eba89d06 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 3 Jan 2023 11:47:15 -0500 Subject: [PATCH 58/65] fix hardcoded nonce --- src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol index 9cb20b1d6..d53dd4d2c 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol @@ -139,9 +139,11 @@ contract NftVaultBasicE2ETest is BridgeTestBase { (address collection, uint256 tokenId) = bridge.nftAssets(virtualAsset100.id); uint64 auxData = uint64(registry.addressCount() - 1); + uint256 interactionNonce = ROLLUP_ENCODER.getNextNonce(); + vm.expectEmit(true, true, false, false); // ran test and determined the interaction nonce of the tx will be 128 - emit NftDeposit(128, collection, tokenId); + emit NftDeposit(interactionNonce, collection, tokenId); ROLLUP_ENCODER.defiInteractionL2(bridgeId, virtualAsset100, emptyAsset, virtualAsset1, emptyAsset, auxData, 1); ROLLUP_ENCODER.processRollupAndGetBridgeResult(); From 9f7be07392dbb98f239cab3829f8a0888947a140 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 3 Jan 2023 15:08:36 -0500 Subject: [PATCH 59/65] remove unreachable code --- src/bridges/registry/AddressRegistry.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index a9f0a8651..cc3b68043 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -65,8 +65,6 @@ contract AddressRegistry is BridgeBase { address toRegister = address(uint160(_totalInputValue)); registerAddress(toRegister); return (0, 0, false); - } else { - revert ErrorLib.InvalidInput(); } } From c50d70271ff1dc49379689d900e5dc360f76a631 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 3 Jan 2023 15:12:41 -0500 Subject: [PATCH 60/65] test invalid input amount --- .../registry/AddressRegistryUnitTest.t.sol | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol index ba71e3a23..a66fcd274 100644 --- a/src/test/bridges/registry/AddressRegistryUnitTest.t.sol +++ b/src/test/bridges/registry/AddressRegistryUnitTest.t.sol @@ -15,7 +15,12 @@ contract AddressRegistryUnitTest is BridgeTestBase { address private rollupProcessor; AddressRegistry private bridge; uint256 public maxInt = type(uint160).max; - AztecTypes.AztecAsset private ethAsset; + AztecTypes.AztecAsset private ethAsset = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + AztecTypes.AztecAsset private virtualAsset = + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + AztecTypes.AztecAsset private daiAsset = + AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); event AddressRegistered(uint256 indexed addressCount, address indexed registeredAddress); @@ -42,35 +47,37 @@ contract AddressRegistryUnitTest is BridgeTestBase { } function testInvalidInputAssetType() public { - AztecTypes.AztecAsset memory inputAsset = - AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); - vm.expectRevert(ErrorLib.InvalidInputA.selector); - bridge.convert(inputAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); + bridge.convert(daiAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0)); } function testInvalidOutputAssetType() public { - AztecTypes.AztecAsset memory inputAsset = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); - AztecTypes.AztecAsset memory outputAsset = - AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); vm.expectRevert(ErrorLib.InvalidOutputA.selector); - bridge.convert(inputAsset, emptyAsset, outputAsset, emptyAsset, 0, 0, 0, address(0)); + bridge.convert(ethAsset, emptyAsset, daiAsset, emptyAsset, 0, 0, 0, address(0)); } - function testGetBackMaxVirtualAssets() public { - vm.warp(block.timestamp + 1 days); + function testInvalidInputAmount() public { + vm.expectRevert(ErrorLib.InvalidInputAmount.selector); - AztecTypes.AztecAsset memory inputAssetA = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); + bridge.convert( + ethAsset, + emptyAsset, + virtualAsset, + emptyAsset, + 0, // _totalInputValue + 0, // _interactionNonce + 0, // _auxData + address(0x0) + ); + } - AztecTypes.AztecAsset memory outputAssetA = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + function testGetBackMaxVirtualAssets() public { + vm.warp(block.timestamp + 1 days); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - inputAssetA, + ethAsset, emptyAsset, - outputAssetA, + virtualAsset, emptyAsset, 1, // _totalInputValue 0, // _interactionNonce @@ -86,21 +93,15 @@ contract AddressRegistryUnitTest is BridgeTestBase { function testRegistringAnAddress() public { vm.warp(block.timestamp + 1 days); - AztecTypes.AztecAsset memory inputAssetA = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - - AztecTypes.AztecAsset memory outputAssetA = - AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); - uint160 inputAmount = uint160(0x2e782B05290A7fFfA137a81a2bad2446AD0DdFEA); vm.expectEmit(true, true, false, false); emit AddressRegistered(0, address(inputAmount)); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = bridge.convert( - inputAssetA, + virtualAsset, emptyAsset, - outputAssetA, + virtualAsset, emptyAsset, inputAmount, // _totalInputValue 0, // _interactionNonce From f9fd54e4f2f7333ae0da2ed8bb7f5d109a1be148 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 3 Jan 2023 20:40:10 -0500 Subject: [PATCH 61/65] incorporat e review suggestions --- .../nft-basic/{NftVault.sol => NFTVault.sol} | 54 +++++++----------- ...loyment.s.sol => NFTVaultDeployment.s.sol} | 16 +++--- .../registry/AddressRegistryDeployment.s.sol | 2 +- .../{NftVaultGas.s.sol => NFTVaultGas.s.sol} | 21 +++---- src/gas/nft-basic/README.md | 2 +- ...tBasicE2E.t.sol => NFTVaultBasicE2E.t.sol} | 57 ++++++++++--------- ...asicUnit.t.sol => NFTVaultBasicUnit.t.sol} | 52 ++++++++--------- 7 files changed, 98 insertions(+), 106 deletions(-) rename src/bridges/nft-basic/{NftVault.sol => NFTVault.sol} (73%) rename src/deployment/nft-basic/{NftVaultDeployment.s.sol => NFTVaultDeployment.s.sol} (67%) rename src/gas/nft-basic/{NftVaultGas.s.sol => NFTVaultGas.s.sol} (85%) rename src/test/bridges/nft-basic/{NftVaultBasicE2E.t.sol => NFTVaultBasicE2E.t.sol} (79%) rename src/test/bridges/nft-basic/{NftVaultBasicUnit.t.sol => NFTVaultBasicUnit.t.sol} (93%) diff --git a/src/bridges/nft-basic/NftVault.sol b/src/bridges/nft-basic/NFTVault.sol similarity index 73% rename from src/bridges/nft-basic/NftVault.sol rename to src/bridges/nft-basic/NFTVault.sol index 46b27a81b..65ed56263 100644 --- a/src/bridges/nft-basic/NftVault.sol +++ b/src/bridges/nft-basic/NFTVault.sol @@ -14,20 +14,20 @@ import {AddressRegistry} from "../registry/AddressRegistry.sol"; * @notice You can use this contract to hold your NFTs on Aztec. Whoever holds the corresponding virutal asset note can withdraw the NFT. * @dev This bridge demonstrates basic functionality for an NFT bridge. This may be extended to support more features. */ -contract NftVault is BridgeBase { - struct NftAsset { +contract NFTVault is BridgeBase { + struct NFTAsset { address collection; uint256 tokenId; } AddressRegistry public immutable REGISTRY; - mapping(uint256 => NftAsset) public nftAssets; + mapping(uint256 => NFTAsset) public nftAssets; error InvalidVirtualAssetId(); - event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); - event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NFTDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NFTWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); /** * @notice Set the addresses of RollupProcessor and AddressRegistry @@ -39,10 +39,10 @@ contract NftVault is BridgeBase { } /** - * @notice Function for the first step of a NFT deposit, a NFT withdrawal, or transfer to another NftVault. + * @notice Function for the first step of a NFT deposit, a NFT withdrawal, or transfer to another NFTVault. * @dev This method can only be called from the RollupProcessor. The first step of the * deposit flow returns a virutal asset note that will represent the NFT on Aztec. After the - * virutal asset note is received on Aztec, the user calls transferFromAndMatch which deposits the NFT + * virutal asset note is received on Aztec, the user calls matchAndPull which deposits the NFT * into Aztec and matches it with the virtual asset. When the virutal asset is sent to this function * it is burned and the NFT is sent to the recipient passed in _auxData. * @@ -90,9 +90,8 @@ contract NftVault is BridgeBase { return (1, 0, false); } else if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - && _outputAssetA.assetType == AztecTypes.AztecAssetType.ETH ) { - NftAsset memory token = nftAssets[_inputAssetA.id]; + NFTAsset memory token = nftAssets[_inputAssetA.id]; if (token.collection == address(0x0)) { revert ErrorLib.InvalidInputA(); } @@ -102,46 +101,37 @@ contract NftVault is BridgeBase { revert ErrorLib.InvalidAuxData(); } delete nftAssets[_inputAssetA.id]; - IERC721(token.collection).transferFrom(address(this), to, token.tokenId); - emit NftWithdraw(_inputAssetA.id, token.collection, token.tokenId); - return (0, 0, false); - } else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - ) { - NftAsset memory token = nftAssets[_inputAssetA.id]; - if (token.collection == address(0x0)) { - revert ErrorLib.InvalidInputA(); + emit NFTWithdraw(_inputAssetA.id, token.collection, token.tokenId); + + if(_outputAssetA.assetType == AztecTypes.AztecAssetType.ETH){ + IERC721(token.collection).transferFrom(address(this), to, token.tokenId); + return (0, 0, false); + } else { + IERC721(token.collection).approve(to, token.tokenId); + NFTVault(to).matchAndPull(_interactionNonce, token.collection, token.tokenId); + return (1, 0, false); } - - address to = REGISTRY.addresses(_auxData); - delete nftAssets[_inputAssetA.id]; - - IERC721(token.collection).approve(to, token.tokenId); - NftVault(to).transferFromAndMatch(_interactionNonce, token.collection, token.tokenId); - - return (1, 0, false); } } /** - * @notice Function for the second step of a NFT deposit or for transfers from other NftVaults. + * @notice Function for the second step of a NFT deposit or for transfers from other NFTVaults. * @dev For a deposit, this method is called by an Ethereum L1 account that owns the NFT to deposit. * The user must approve this bridge contract to transfer the users NFT before this function * is called. This function assumes the NFT contract complies with the ERC721 standard. - * For a transfer from another NftVault, this method is called by the NftVault that is sending the NFT. + * For a transfer from another NFTVault, this method is called by the NFTVault that is sending the NFT. * * @param _virtualAssetId - the virutal asset id of the note returned in the deposit step of the convert function * @param _collection - collection address of the NFT * @param _tokenId - the token id of the NFT */ - function transferFromAndMatch(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { + function matchAndPull(uint256 _virtualAssetId, address _collection, uint256 _tokenId) external { if (nftAssets[_virtualAssetId].collection != address(0x0)) { revert InvalidVirtualAssetId(); } - nftAssets[_virtualAssetId] = NftAsset({collection: _collection, tokenId: _tokenId}); + nftAssets[_virtualAssetId] = NFTAsset({collection: _collection, tokenId: _tokenId}); IERC721(_collection).transferFrom(msg.sender, address(this), _tokenId); - emit NftDeposit(_virtualAssetId, _collection, _tokenId); + emit NFTDeposit(_virtualAssetId, _collection, _tokenId); } } diff --git a/src/deployment/nft-basic/NftVaultDeployment.s.sol b/src/deployment/nft-basic/NFTVaultDeployment.s.sol similarity index 67% rename from src/deployment/nft-basic/NftVaultDeployment.s.sol rename to src/deployment/nft-basic/NFTVaultDeployment.s.sol index 2af23aa2f..9d3e7dfe4 100644 --- a/src/deployment/nft-basic/NftVaultDeployment.s.sol +++ b/src/deployment/nft-basic/NFTVaultDeployment.s.sol @@ -3,17 +3,17 @@ pragma solidity >=0.8.4; import {BaseDeployment} from "../base/BaseDeployment.s.sol"; -import {NftVault} from "../../bridges/nft-basic/NftVault.sol"; +import {NFTVault} from "../../bridges/nft-basic/NFTVault.sol"; import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; -contract NftVaultDeployment is BaseDeployment { +contract NFTVaultDeployment is BaseDeployment { function deploy(address _addressRegistry) public returns (address) { - emit log("Deploying NftVault bridge"); + emit log("Deploying NFTVault bridge"); vm.broadcast(); - NftVault bridge = new NftVault(ROLLUP_PROCESSOR, _addressRegistry); + NFTVault bridge = new NFTVault(ROLLUP_PROCESSOR, _addressRegistry); - emit log_named_address("NftVault bridge deployed to", address(bridge)); + emit log_named_address("NFTVault bridge deployed to", address(bridge)); return address(bridge); } @@ -21,8 +21,8 @@ contract NftVaultDeployment is BaseDeployment { function deployAndList(address _addressRegistry) public returns (address) { address bridge = deploy(_addressRegistry); - uint256 addressId = listBridge(bridge, 400000); - emit log_named_uint("NftVault bridge address id", addressId); + uint256 addressId = listBridge(bridge, 135500); + emit log_named_uint("NFTVault bridge address id", addressId); return bridge; } @@ -34,7 +34,7 @@ contract NftVaultDeployment is BaseDeployment { emit log_named_address("AddressRegistry bridge deployed to", address(bridge)); - uint256 addressId = listBridge(address(bridge), 400000); + uint256 addressId = listBridge(address(bridge), 120500); emit log_named_uint("AddressRegistry bridge address id", addressId); return address(bridge); diff --git a/src/deployment/registry/AddressRegistryDeployment.s.sol b/src/deployment/registry/AddressRegistryDeployment.s.sol index 1f42a63ff..52cd58b6b 100644 --- a/src/deployment/registry/AddressRegistryDeployment.s.sol +++ b/src/deployment/registry/AddressRegistryDeployment.s.sol @@ -20,7 +20,7 @@ contract AddressRegistryDeployment is BaseDeployment { function deployAndList() public returns (address) { address bridge = deploy(); - uint256 addressId = listBridge(bridge, 400000); + uint256 addressId = listBridge(bridge, 120500); emit log_named_uint("AddressRegistry bridge address id", addressId); return bridge; diff --git a/src/gas/nft-basic/NftVaultGas.s.sol b/src/gas/nft-basic/NFTVaultGas.s.sol similarity index 85% rename from src/gas/nft-basic/NftVaultGas.s.sol rename to src/gas/nft-basic/NFTVaultGas.s.sol index 48c9f9d5d..bb6dcbb31 100644 --- a/src/gas/nft-basic/NftVaultGas.s.sol +++ b/src/gas/nft-basic/NFTVaultGas.s.sol @@ -4,10 +4,10 @@ pragma solidity >=0.8.4; import {AddressRegistry} from "../../bridges/registry/AddressRegistry.sol"; import {AddressRegistryDeployment} from "../../deployment/registry/AddressRegistryDeployment.s.sol"; -import {NftVault} from "../../bridges/nft-basic/NftVault.sol"; +import {NFTVault} from "../../bridges/nft-basic/NFTVault.sol"; import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; -import {NftVaultDeployment} from "../../deployment/nft-basic/NftVaultDeployment.s.sol"; +import {NFTVaultDeployment} from "../../deployment/nft-basic/NFTVaultDeployment.s.sol"; import {GasBase} from "../base/GasBase.sol"; import {ERC721PresetMinterPauserAutoId} from @@ -17,10 +17,10 @@ interface IRead { function defiBridgeProxy() external view returns (address); } -contract NftVaultGas is NftVaultDeployment { +contract NFTVaultGas is NFTVaultDeployment { GasBase internal gasBase; - NftVault internal bridge; - NftVault internal bridge2; + NFTVault internal bridge; + NFTVault internal bridge2; ERC721PresetMinterPauserAutoId internal nftContract; address internal registry; uint256 internal registryAddressId; @@ -29,7 +29,7 @@ contract NftVaultGas is NftVaultDeployment { AztecTypes.AztecAsset private eth = AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.ETH}); AztecTypes.AztecAsset private virtualAsset = - AztecTypes.AztecAsset({id: 100, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); + AztecTypes.AztecAsset({id: 0, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); AztecTypes.AztecAsset private virtualAsset128 = AztecTypes.AztecAsset({id: 128, erc20Address: address(0), assetType: AztecTypes.AztecAssetType.VIRTUAL}); @@ -71,12 +71,13 @@ contract NftVaultGas is NftVaultDeployment { // deposit nft { vm.broadcast(); - NftVault(bridge).transferFromAndMatch(virtualAsset.id, address(nftContract), 0); + NFTVault(bridge).matchAndPull(virtualAsset.id, address(nftContract), 0); } // transfer nft { + vm.broadcast(); - gasBase.convert(bridge, virtualAsset, empty, virtualAsset128, empty, 1, 128, 2, address(0), 400000); + gasBase.convert(bridge, virtualAsset, empty, virtualAsset128, empty, 1, 128, 2, address(0), 4000000); } // withdraw nft { @@ -87,7 +88,7 @@ contract NftVaultGas is NftVaultDeployment { function _registerAddress(address _toRegister) internal { // get registry virtual asset - gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 400000); + gasBase.convert(address(registry), eth, empty, virtualAsset, empty, 1, 0, 0, address(0), 4000000); // register address gasBase.convert( address(registry), @@ -99,7 +100,7 @@ contract NftVaultGas is NftVaultDeployment { 0, 0, address(0), - 400000 + 4000000 ); } } diff --git a/src/gas/nft-basic/README.md b/src/gas/nft-basic/README.md index ef7d577da..44564d1c7 100644 --- a/src/gas/nft-basic/README.md +++ b/src/gas/nft-basic/README.md @@ -12,5 +12,5 @@ anvil --fork-url https://mainnet.infura.io/v3/${API_KEY} ``` 3. run this command ``` -forge script src/gas/nft-basic/NftVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -vvvv +forge script src/gas/nft-basic/NFTVaultGas.s.sol --fork-url http://localhost:8545 --sig "measure()" --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -vvvv ``` \ No newline at end of file diff --git a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol b/src/test/bridges/nft-basic/NFTVaultBasicE2E.t.sol similarity index 79% rename from src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol rename to src/test/bridges/nft-basic/NFTVaultBasicE2E.t.sol index d53dd4d2c..6858227e8 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicE2E.t.sol +++ b/src/test/bridges/nft-basic/NFTVaultBasicE2E.t.sol @@ -6,7 +6,7 @@ import {BridgeTestBase} from "./../../aztec/base/BridgeTestBase.sol"; import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; // Example-specific imports -import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; +import {NFTVault} from "../../../bridges/nft-basic/NFTVault.sol"; import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; import {ERC721PresetMinterPauserAutoId} from @@ -16,9 +16,9 @@ import {ERC721PresetMinterPauserAutoId} from * @notice The purpose of this test is to test the bridge in an environment that is as close to the final deployment * as possible without spinning up all the rollup infrastructure (sequencer, proof generator etc.). */ -contract NftVaultBasicE2ETest is BridgeTestBase { - NftVault internal bridge; - NftVault internal bridge2; +contract NFTVaultBasicE2ETest is BridgeTestBase { + NFTVault internal bridge; + NFTVault internal bridge2; AddressRegistry private registry; ERC721PresetMinterPauserAutoId private nftContract; @@ -37,13 +37,13 @@ contract NftVaultBasicE2ETest is BridgeTestBase { AztecTypes.AztecAsset private erc20InputAsset = AztecTypes.AztecAsset({id: 1, erc20Address: DAI, assetType: AztecTypes.AztecAssetType.ERC20}); - event NftDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); - event NftWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NFTDeposit(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); + event NFTWithdraw(uint256 indexed virtualAssetId, address indexed collection, uint256 indexed tokenId); function setUp() public { registry = new AddressRegistry(address(ROLLUP_PROCESSOR)); - bridge = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); - bridge2 = new NftVault(address(ROLLUP_PROCESSOR), address(registry)); + bridge = new NFTVault(address(ROLLUP_PROCESSOR), address(registry)); + bridge2 = new NFTVault(address(ROLLUP_PROCESSOR), address(registry)); nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); nftContract.mint(address(this)); @@ -56,16 +56,16 @@ contract NftVaultBasicE2ETest is BridgeTestBase { ethAsset = ROLLUP_ENCODER.getRealAztecAsset(address(0)); vm.label(address(registry), "AddressRegistry Bridge"); - vm.label(address(bridge), "NftVault Bridge"); + vm.label(address(bridge), "NFTVault Bridge"); // Impersonate the multi-sig to add a new bridge vm.startPrank(MULTI_SIG); // WARNING: If you set this value too low the interaction will fail for seemingly no reason! // OTOH if you se it too high bridge users will pay too much - ROLLUP_PROCESSOR.setSupportedBridge(address(registry), 120000); - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 120000); - ROLLUP_PROCESSOR.setSupportedBridge(address(bridge2), 120000); + ROLLUP_PROCESSOR.setSupportedBridge(address(registry), 120500); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge), 135500); + ROLLUP_PROCESSOR.setSupportedBridge(address(bridge2), 135500); vm.stopPrank(); @@ -73,21 +73,21 @@ contract NftVaultBasicE2ETest is BridgeTestBase { registryBridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 2; bridgeId = ROLLUP_PROCESSOR.getSupportedBridgesLength() - 1; bridge2Id = ROLLUP_PROCESSOR.getSupportedBridgesLength(); - // get virutal assets to register an address + // get virtual assets to register an address ROLLUP_ENCODER.defiInteractionL2(registryBridgeId, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); - ROLLUP_ENCODER.processRollupAndGetBridgeResult(); - // get virutal assets to register 2nd NftVault + ROLLUP_ENCODER.processRollup(); + // get virtual assets to register 2nd NFTVault ROLLUP_ENCODER.defiInteractionL2(registryBridgeId, ethAsset, emptyAsset, virtualAsset1, emptyAsset, 0, 1); - ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + ROLLUP_ENCODER.processRollup(); // register an address uint160 inputAmount = uint160(REGISTER_ADDRESS); ROLLUP_ENCODER.defiInteractionL2( registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, inputAmount ); - ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + ROLLUP_ENCODER.processRollup(); - // register 2nd NftVault in AddressRegistry + // register 2nd NFTVault in AddressRegistry uint160 bridge2AddressAmount = uint160(address(bridge2)); ROLLUP_ENCODER.defiInteractionL2( registryBridgeId, virtualAsset1, emptyAsset, virtualAsset1, emptyAsset, 0, bridge2AddressAmount @@ -106,9 +106,9 @@ contract NftVaultBasicE2ETest is BridgeTestBase { address collection = address(nftContract); - vm.expectEmit(true, true, false, false); - emit NftDeposit(virtualAsset100.id, collection, tokenIdToDeposit); - bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); + vm.expectEmit(true, true, true, false); + emit NFTDeposit(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.matchAndPull(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -119,7 +119,7 @@ contract NftVaultBasicE2ETest is BridgeTestBase { uint64 auxData = uint64(registry.addressCount() - 2); vm.expectEmit(true, true, false, false); - emit NftWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); + emit NFTWithdraw(virtualAsset100.id, address(nftContract), tokenIdToDeposit); ROLLUP_ENCODER.defiInteractionL2(bridgeId, virtualAsset100, emptyAsset, ethAsset, emptyAsset, auxData, 1); (uint256 outputValueA, uint256 outputValueB, bool isAsync) = ROLLUP_ENCODER.processRollupAndGetBridgeResult(); @@ -141,15 +141,16 @@ contract NftVaultBasicE2ETest is BridgeTestBase { uint256 interactionNonce = ROLLUP_ENCODER.getNextNonce(); - vm.expectEmit(true, true, false, false); - // ran test and determined the interaction nonce of the tx will be 128 - emit NftDeposit(interactionNonce, collection, tokenId); + vm.expectEmit(true, true, true, false, address(bridge)); + emit NFTWithdraw(virtualAsset100.id, collection, tokenId); + vm.expectEmit(true, true, true, false, address(bridge2)); + emit NFTDeposit(interactionNonce, collection, tokenId); ROLLUP_ENCODER.defiInteractionL2(bridgeId, virtualAsset100, emptyAsset, virtualAsset1, emptyAsset, auxData, 1); - ROLLUP_ENCODER.processRollupAndGetBridgeResult(); + ROLLUP_ENCODER.processRollup(); - // check that the nft was transferred to the second NftVault - (address returnedCollection, uint256 returnedId) = bridge2.nftAssets(128); + // check that the nft was transferred to the second NFTVault + (address returnedCollection, uint256 returnedId) = bridge2.nftAssets(interactionNonce); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); } diff --git a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol b/src/test/bridges/nft-basic/NFTVaultBasicUnit.t.sol similarity index 93% rename from src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol rename to src/test/bridges/nft-basic/NFTVaultBasicUnit.t.sol index d6cc55694..7fdf5ce43 100644 --- a/src/test/bridges/nft-basic/NftVaultBasicUnit.t.sol +++ b/src/test/bridges/nft-basic/NFTVaultBasicUnit.t.sol @@ -8,12 +8,12 @@ import {AztecTypes} from "rollup-encoder/libraries/AztecTypes.sol"; // Example-specific imports import {ERC721PresetMinterPauserAutoId} from "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; -import {NftVault} from "../../../bridges/nft-basic/NftVault.sol"; +import {NFTVault} from "../../../bridges/nft-basic/NFTVault.sol"; import {ErrorLib} from "../../../bridges/base/ErrorLib.sol"; import {AddressRegistry} from "../../../bridges/registry/AddressRegistry.sol"; // @notice The purpose of this test is to directly test convert functionality of the bridge. -contract NftVaultBasicUnitTest is BridgeTestBase { +contract NFTVaultBasicUnitTest is BridgeTestBase { struct NftAsset { address collection; uint256 id; @@ -21,8 +21,8 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address private rollupProcessor; - NftVault private bridge; - NftVault private bridge2; + NFTVault private bridge; + NFTVault private bridge2; ERC721PresetMinterPauserAutoId private nftContract; uint256 private tokenIdToDeposit = 1; AddressRegistry private registry; @@ -47,8 +47,8 @@ contract NftVaultBasicUnitTest is BridgeTestBase { rollupProcessor = address(this); registry = new AddressRegistry(rollupProcessor); - bridge = new NftVault(rollupProcessor, address(registry)); - bridge2 = new NftVault(rollupProcessor, address(registry)); + bridge = new NFTVault(rollupProcessor, address(registry)); + bridge2 = new NFTVault(rollupProcessor, address(registry)); nftContract = new ERC721PresetMinterPauserAutoId("test", "NFT", ""); nftContract.mint(address(this)); nftContract.mint(address(this)); @@ -124,7 +124,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { vm.warp(block.timestamp + 1 days); address collection = address(nftContract); - bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.matchAndPull(virtualAsset100.id, collection, tokenIdToDeposit); (address returnedCollection, uint256 returnedId) = bridge.nftAssets(virtualAsset100.id); assertEq(returnedId, tokenIdToDeposit, "nft token id does not match input"); assertEq(returnedCollection, collection, "collection data does not match"); @@ -137,7 +137,24 @@ contract NftVaultBasicUnitTest is BridgeTestBase { address collection = address(nftContract); vm.expectRevert(); - bridge.transferFromAndMatch(virtualAsset100.id, collection, tokenIdToDeposit); + bridge.matchAndPull(virtualAsset100.id, collection, tokenIdToDeposit); + } + + // should fail because no withdraw address has been registered with this id + function testWithdrawUnregisteredWithdrawAddress() public { + testDeposit(); + uint64 auxData = 1000; + vm.expectRevert(ErrorLib.InvalidAuxData.selector); + bridge.convert( + virtualAsset100, // _inputAssetA + emptyAsset, // _inputAssetB + ethAsset, // _outputAssetA + emptyAsset, // _outputAssetB + 1, // _totalInputValue + 0, // _interactionNonce + auxData, + address(0) + ); } function testWithdraw() public { @@ -168,24 +185,7 @@ contract NftVaultBasicUnitTest is BridgeTestBase { function testWithdrawUnregisteredNft() public { testDeposit(); uint64 auxData = uint64(registry.addressCount()); - vm.expectRevert(); - bridge.convert( - virtualAsset1, // _inputAssetA - emptyAsset, // _inputAssetB - ethAsset, // _outputAssetA - emptyAsset, // _outputAssetB - 1, // _totalInputValue - 0, // _interactionNonce - auxData, - address(0) - ); - } - - // should fail because no withdraw address has been registered with this id - function testWithdrawUnregisteredWithdrawAddress() public { - testDeposit(); - uint64 auxData = 1000; - vm.expectRevert(); + vm.expectRevert(ErrorLib.InvalidInputA.selector); bridge.convert( virtualAsset1, // _inputAssetA emptyAsset, // _inputAssetB From e21dd63899046d61540fe16c82b0dfee4f62fb87 Mon Sep 17 00:00:00 2001 From: josh c Date: Tue, 3 Jan 2023 20:41:04 -0500 Subject: [PATCH 62/65] Delete .env --- .env | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 8dab26b54..000000000 --- a/.env +++ /dev/null @@ -1,3 +0,0 @@ -PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -network=mainnet -simulateAdmin=false \ No newline at end of file From 7cef40cce44d2e4daea8c5eed4137efb6cb64307 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 3 Jan 2023 20:42:22 -0500 Subject: [PATCH 63/65] fmt --- src/bridges/nft-basic/NFTVault.sol | 8 +++----- src/gas/nft-basic/NFTVaultGas.s.sol | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/bridges/nft-basic/NFTVault.sol b/src/bridges/nft-basic/NFTVault.sol index 65ed56263..dec468119 100644 --- a/src/bridges/nft-basic/NFTVault.sol +++ b/src/bridges/nft-basic/NFTVault.sol @@ -88,9 +88,7 @@ contract NFTVault is BridgeBase { && _outputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL ) { return (1, 0, false); - } else if ( - _inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL - ) { + } else if (_inputAssetA.assetType == AztecTypes.AztecAssetType.VIRTUAL) { NFTAsset memory token = nftAssets[_inputAssetA.id]; if (token.collection == address(0x0)) { revert ErrorLib.InvalidInputA(); @@ -102,8 +100,8 @@ contract NFTVault is BridgeBase { } delete nftAssets[_inputAssetA.id]; emit NFTWithdraw(_inputAssetA.id, token.collection, token.tokenId); - - if(_outputAssetA.assetType == AztecTypes.AztecAssetType.ETH){ + + if (_outputAssetA.assetType == AztecTypes.AztecAssetType.ETH) { IERC721(token.collection).transferFrom(address(this), to, token.tokenId); return (0, 0, false); } else { diff --git a/src/gas/nft-basic/NFTVaultGas.s.sol b/src/gas/nft-basic/NFTVaultGas.s.sol index bb6dcbb31..ae0593ed3 100644 --- a/src/gas/nft-basic/NFTVaultGas.s.sol +++ b/src/gas/nft-basic/NFTVaultGas.s.sol @@ -75,7 +75,6 @@ contract NFTVaultGas is NFTVaultDeployment { } // transfer nft { - vm.broadcast(); gasBase.convert(bridge, virtualAsset, empty, virtualAsset128, empty, 1, 128, 2, address(0), 4000000); } From a4e70caf2c1341701bde93eaa03d0336de8401c5 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 10 Jan 2023 14:34:34 -0500 Subject: [PATCH 64/65] fmt --- lib/forge-std | 2 +- lib/rollup-encoder | 2 +- src/aztec/Subsidy.sol | 27 +++++++++++-------- src/bridges/angle/AngleSLPBridge.sol | 4 +-- src/bridges/base/BridgeBase.sol | 4 +-- src/bridges/curve/CurveStEthBridge.sol | 2 +- src/bridges/dca/BiDCABridge.sol | 4 +-- src/bridges/dca/UniswapDCABridge.sol | 2 +- src/bridges/donation/DonationBridge.sol | 2 +- src/bridges/element/ElementBridge.sol | 4 +-- src/bridges/erc4626/ERC4626Bridge.sol | 4 +-- src/bridges/example/ExampleBridge.sol | 4 +-- src/bridges/lido/LidoBridge.sol | 2 +- src/bridges/liquity/StabilityPoolBridge.sol | 4 +-- src/bridges/liquity/StakingBridge.sol | 4 +-- src/bridges/liquity/TroveBridge.sol | 6 ++--- src/bridges/uniswap/UniswapBridge.sol | 4 +-- src/bridges/yearn/YearnBridge.sol | 4 +-- src/gas/angle/AngleSLPGas.s.sol | 2 +- src/gas/erc4626/ERC4626Gas.s.sol | 2 +- src/gas/liquity/TroveBridgeGas.s.sol | 2 +- src/gas/uniswap/UniswapGas.s.sol | 2 +- src/test/bridges/erc4626/mocks/WETHVault.sol | 2 +- .../bridges/liquity/utils/MockPriceFeed.sol | 2 +- 24 files changed, 51 insertions(+), 46 deletions(-) diff --git a/lib/forge-std b/lib/forge-std index d666309ed..b8a11f5ba 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit d666309ed272e7fa16fa35f28d63ee6442df45fc +Subproject commit b8a11f5ba2eaac60949324c1f50b2f748f38b4be diff --git a/lib/rollup-encoder b/lib/rollup-encoder index c3ce0d8c6..64b9c1183 160000 --- a/lib/rollup-encoder +++ b/lib/rollup-encoder @@ -1 +1 @@ -Subproject commit c3ce0d8c691bb6a9361156e34e8e693608a32698 +Subproject commit 64b9c1183b76b30006f9954cccf2d39055c72644 diff --git a/src/aztec/Subsidy.sol b/src/aztec/Subsidy.sol index 4d9bf2a78..2e3566e59 100644 --- a/src/aztec/Subsidy.sol +++ b/src/aztec/Subsidy.sol @@ -60,7 +60,7 @@ contract Subsidy is ISubsidy { // @dev Using min possible `msg.value` upon subsidizing in order to limit possibility of front running attacks // --> e.g. attacker front-running real subsidy tx by sending 1 wei value tx making the real one revert - uint256 public constant override(ISubsidy) MIN_SUBSIDY_VALUE = 1e17; + uint256 public constant override (ISubsidy) MIN_SUBSIDY_VALUE = 1e17; // address bridge => uint256 criteria => Subsidy subsidy mapping(address => mapping(uint256 => Subsidy)) public subsidies; @@ -73,7 +73,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary The address of the beneficiary to query * @return The amount of claimable ETH for `_beneficiary` */ - function claimableAmount(address _beneficiary) external view override(ISubsidy) returns (uint256) { + function claimableAmount(address _beneficiary) external view override (ISubsidy) returns (uint256) { return beneficiaries[_beneficiary].claimable; } @@ -82,7 +82,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary The address of the beneficiary to check * @return True if the `_beneficiary` is registered, false otherwise */ - function isRegistered(address _beneficiary) external view override(ISubsidy) returns (bool) { + function isRegistered(address _beneficiary) external view override (ISubsidy) returns (bool) { return beneficiaries[_beneficiary].registered; } @@ -92,7 +92,12 @@ contract Subsidy is ISubsidy { * @param _criteria The criteria of the subsidy * @return The subsidy data object */ - function getSubsidy(address _bridge, uint256 _criteria) external view override(ISubsidy) returns (Subsidy memory) { + function getSubsidy(address _bridge, uint256 _criteria) + external + view + override (ISubsidy) + returns (Subsidy memory) + { return subsidies[_bridge][_criteria]; } @@ -109,7 +114,7 @@ contract Subsidy is ISubsidy { uint256[] calldata _criteria, uint32[] calldata _gasUsage, uint32[] calldata _minGasPerMinute - ) external override(ISubsidy) { + ) external override (ISubsidy) { uint256 criteriasLength = _criteria.length; if (criteriasLength != _gasUsage.length || criteriasLength != _minGasPerMinute.length) { revert ArrayLengthsDoNotMatch(); @@ -132,7 +137,7 @@ contract Subsidy is ISubsidy { * IDefiBridge.convert(...) function to be as predictable as possible. If the cost is too variable users would * overpay since RollupProcessor works with constant gas limits. */ - function registerBeneficiary(address _beneficiary) external override(ISubsidy) { + function registerBeneficiary(address _beneficiary) external override (ISubsidy) { beneficiaries[_beneficiary].registered = true; emit BeneficiaryRegistered(_beneficiary); } @@ -147,7 +152,7 @@ contract Subsidy is ISubsidy { * 3) subsidy.gasUsage not set: `subsidy.gasUsage` == 0, * 4) ETH value sent too low: `msg.value` < `MIN_SUBSIDY_VALUE`. */ - function subsidize(address _bridge, uint256 _criteria, uint32 _gasPerMinute) external payable override(ISubsidy) { + function subsidize(address _bridge, uint256 _criteria, uint32 _gasPerMinute) external payable override (ISubsidy) { if (msg.value < MIN_SUBSIDY_VALUE) { revert SubsidyTooLow(); } @@ -180,7 +185,7 @@ contract Subsidy is ISubsidy { * @param _criteria A value defining the specific bridge call to subsidize * @dev Reverts if `available` is 0. */ - function topUp(address _bridge, uint256 _criteria) external payable override(ISubsidy) { + function topUp(address _bridge, uint256 _criteria) external payable override (ISubsidy) { // Caching subsidy in order to minimize number of SLOADs and SSTOREs Subsidy memory sub = subsidies[_bridge][_criteria]; @@ -202,7 +207,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary Address which is going to receive the subsidy * @return subsidy ETH amount which was added to the `_beneficiary` claimable balance */ - function claimSubsidy(uint256 _criteria, address _beneficiary) external override(ISubsidy) returns (uint256) { + function claimSubsidy(uint256 _criteria, address _beneficiary) external override (ISubsidy) returns (uint256) { if (_beneficiary == address(0)) { return 0; } @@ -245,7 +250,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary Address which is going to receive the subsidy * @return - ETH amount which was sent to the `_beneficiary` */ - function withdraw(address _beneficiary) external override(ISubsidy) returns (uint256) { + function withdraw(address _beneficiary) external override (ISubsidy) returns (uint256) { uint256 withdrawableBalance = beneficiaries[_beneficiary].claimable; // Immediately updating the balance to avoid re-entrancy attack beneficiaries[_beneficiary].claimable = 0; @@ -279,7 +284,7 @@ contract Subsidy is ISubsidy { */ function setGasUsageAndMinGasPerMinute(uint256 _criteria, uint32 _gasUsage, uint32 _minGasPerMinute) public - override(ISubsidy) + override (ISubsidy) { // Loading `sub` first in order to not overwrite `sub.available` in case this function was already called // and a subsidy was set. diff --git a/src/bridges/angle/AngleSLPBridge.sol b/src/bridges/angle/AngleSLPBridge.sol index 7b8f1ad00..c75c333e3 100644 --- a/src/bridges/angle/AngleSLPBridge.sol +++ b/src/bridges/angle/AngleSLPBridge.sol @@ -89,7 +89,7 @@ contract AngleSLPBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { address inputAssetA; address outputAssetA; @@ -144,7 +144,7 @@ contract AngleSLPBridge is BridgeBase { AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint64 _auxData - ) public pure override(BridgeBase) returns (uint256) { + ) public pure override (BridgeBase) returns (uint256) { if (_auxData > 1) { revert ErrorLib.InvalidAuxData(); } diff --git a/src/bridges/base/BridgeBase.sol b/src/bridges/base/BridgeBase.sol index 235dc01bb..21a227700 100644 --- a/src/bridges/base/BridgeBase.sol +++ b/src/bridges/base/BridgeBase.sol @@ -39,7 +39,7 @@ abstract contract BridgeBase is IDefiBridge { uint256, uint64, address - ) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) { + ) external payable virtual override (IDefiBridge) returns (uint256, uint256, bool) { revert MissingImplementation(); } @@ -50,7 +50,7 @@ abstract contract BridgeBase is IDefiBridge { AztecTypes.AztecAsset calldata, uint256, uint64 - ) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) { + ) external payable virtual override (IDefiBridge) returns (uint256, uint256, bool) { revert ErrorLib.AsyncDisabled(); } diff --git a/src/bridges/curve/CurveStEthBridge.sol b/src/bridges/curve/CurveStEthBridge.sol index 4beda802d..99c9019e5 100644 --- a/src/bridges/curve/CurveStEthBridge.sol +++ b/src/bridges/curve/CurveStEthBridge.sol @@ -71,7 +71,7 @@ contract CurveStEthBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { bool isETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH; bool isWstETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 && _inputAssetA.erc20Address == address(WRAPPED_STETH); diff --git a/src/bridges/dca/BiDCABridge.sol b/src/bridges/dca/BiDCABridge.sol index b8701aab8..d798db9fc 100644 --- a/src/bridges/dca/BiDCABridge.sol +++ b/src/bridges/dca/BiDCABridge.sol @@ -243,7 +243,7 @@ abstract contract BiDCABridge is BridgeBase { uint256 _interactionNonce, uint64 _numTicks, address - ) external payable override(BridgeBase) onlyRollup returns (uint256, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256, uint256, bool) { address inputAssetAddress = _inputAssetA.erc20Address; address outputAssetAddress = _outputAssetA.erc20Address; @@ -289,7 +289,7 @@ abstract contract BiDCABridge is BridgeBase { external payable virtual - override(BridgeBase) + override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool interactionComplete) { diff --git a/src/bridges/dca/UniswapDCABridge.sol b/src/bridges/dca/UniswapDCABridge.sol index b4e0a2c02..6d6ebcf7f 100644 --- a/src/bridges/dca/UniswapDCABridge.sol +++ b/src/bridges/dca/UniswapDCABridge.sol @@ -109,7 +109,7 @@ contract UniswapDCABridge is BiDCABridge { * @dev Reverts if the price is stale or negative * @return Price */ - function getPrice() public virtual override(BiDCABridge) returns (uint256) { + function getPrice() public virtual override (BiDCABridge) returns (uint256) { (, int256 answer,,,) = ORACLE.latestRoundData(); if (answer < 0) { revert NegativePrice(); diff --git a/src/bridges/donation/DonationBridge.sol b/src/bridges/donation/DonationBridge.sol index da274e89f..ef106e66e 100644 --- a/src/bridges/donation/DonationBridge.sol +++ b/src/bridges/donation/DonationBridge.sol @@ -57,7 +57,7 @@ contract DonationBridge is BridgeBase { uint256, uint64 _auxData, address - ) external payable override(BridgeBase) onlyRollup returns (uint256, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256, uint256, bool) { address receiver = donees[_auxData]; if (receiver == address(0)) { diff --git a/src/bridges/element/ElementBridge.sol b/src/bridges/element/ElementBridge.sol index 2a7b5603b..a703b890e 100644 --- a/src/bridges/element/ElementBridge.sol +++ b/src/bridges/element/ElementBridge.sol @@ -428,7 +428,7 @@ contract ElementBridge is BridgeBase { ) external payable - override(BridgeBase) + override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { @@ -602,7 +602,7 @@ contract ElementBridge is BridgeBase { ) external payable - override(BridgeBase) + override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool interactionCompleted) { diff --git a/src/bridges/erc4626/ERC4626Bridge.sol b/src/bridges/erc4626/ERC4626Bridge.sol index 47d7e372c..2e9bea983 100644 --- a/src/bridges/erc4626/ERC4626Bridge.sol +++ b/src/bridges/erc4626/ERC4626Bridge.sol @@ -87,7 +87,7 @@ contract ERC4626Bridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { address inputToken = _inputAssetA.erc20Address; address outputToken = _outputAssetA.erc20Address; @@ -131,7 +131,7 @@ contract ERC4626Bridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public pure override(BridgeBase) returns (uint256) { + ) public pure override (BridgeBase) returns (uint256) { return _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address); } diff --git a/src/bridges/example/ExampleBridge.sol b/src/bridges/example/ExampleBridge.sol index 0ee7aed18..227f57655 100644 --- a/src/bridges/example/ExampleBridge.sol +++ b/src/bridges/example/ExampleBridge.sol @@ -59,7 +59,7 @@ contract ExampleBridge is BridgeBase { uint256, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { // Check the input asset is ERC20 if (_inputAssetA.assetType != AztecTypes.AztecAssetType.ERC20) revert ErrorLib.InvalidInputA(); if (_outputAssetA.erc20Address != _inputAssetA.erc20Address) revert ErrorLib.InvalidOutputA(); @@ -86,7 +86,7 @@ contract ExampleBridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public view override(BridgeBase) returns (uint256) { + ) public view override (BridgeBase) returns (uint256) { return uint256(keccak256(abi.encodePacked(_inputAssetA.erc20Address, _outputAssetA.erc20Address))); } } diff --git a/src/bridges/lido/LidoBridge.sol b/src/bridges/lido/LidoBridge.sol index a3e29db3a..ea4b3404b 100644 --- a/src/bridges/lido/LidoBridge.sol +++ b/src/bridges/lido/LidoBridge.sol @@ -56,7 +56,7 @@ contract LidoBridge is BridgeBase { uint256 _interactionNonce, uint64, address - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool isAsync) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool isAsync) { bool isETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH; bool isWstETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 && _inputAssetA.erc20Address == address(WRAPPED_STETH); diff --git a/src/bridges/liquity/StabilityPoolBridge.sol b/src/bridges/liquity/StabilityPoolBridge.sol index fb9e1e4e8..ef33c1706 100644 --- a/src/bridges/liquity/StabilityPoolBridge.sol +++ b/src/bridges/liquity/StabilityPoolBridge.sol @@ -113,7 +113,7 @@ contract StabilityPoolBridge is BridgeBase, ERC20("StabilityPoolBridge", "SPB") uint256, uint64 _auxData, address - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_inputAssetA.erc20Address == LUSD && _outputAssetA.erc20Address == address(this)) { // Deposit // Provides LUSD to the pool and claim rewards. @@ -151,7 +151,7 @@ contract StabilityPoolBridge is BridgeBase, ERC20("StabilityPoolBridge", "SPB") /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override(ERC20) returns (uint256) { + function totalSupply() public view override (ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/liquity/StakingBridge.sol b/src/bridges/liquity/StakingBridge.sol index 3fbd3ec70..f32fc44c3 100644 --- a/src/bridges/liquity/StakingBridge.sol +++ b/src/bridges/liquity/StakingBridge.sol @@ -104,7 +104,7 @@ contract StakingBridge is BridgeBase, ERC20("StakingBridge", "SB") { uint256, uint64 _auxData, address - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_inputAssetA.erc20Address == LQTY && _outputAssetA.erc20Address == address(this)) { // Deposit // Stake and claim rewards @@ -141,7 +141,7 @@ contract StakingBridge is BridgeBase, ERC20("StakingBridge", "SB") { /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override(ERC20) returns (uint256) { + function totalSupply() public view override (ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/liquity/TroveBridge.sol b/src/bridges/liquity/TroveBridge.sol index 79daf18d5..de8fbe235 100644 --- a/src/bridges/liquity/TroveBridge.sol +++ b/src/bridges/liquity/TroveBridge.sol @@ -193,7 +193,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool) { Status troveStatus = Status(TROVE_MANAGER.getTroveStatus(address(this))); uint256 subsidyCriteria; @@ -283,7 +283,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { // @dev See _repayWithCollateral(...) method for more information about how this callback is entered. function uniswapV3SwapCallback(int256 _amount0Delta, int256 _amount1Delta, bytes calldata _data) external - override(IUniswapV3SwapCallback) + override (IUniswapV3SwapCallback) { // Swaps entirely within 0-liquidity regions are not supported if (_amount0Delta <= 0 && _amount1Delta <= 0) revert InvalidDeltaAmounts(); @@ -353,7 +353,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override(ERC20) returns (uint256) { + function totalSupply() public view override (ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/uniswap/UniswapBridge.sol b/src/bridges/uniswap/UniswapBridge.sol index 5c3bdc6c5..e1c6acebd 100644 --- a/src/bridges/uniswap/UniswapBridge.sol +++ b/src/bridges/uniswap/UniswapBridge.sol @@ -187,7 +187,7 @@ contract UniswapBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { // Accumulate subsidy to _rollupBeneficiary SUBSIDY.claimSubsidy( _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address), _rollupBeneficiary @@ -319,7 +319,7 @@ contract UniswapBridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public pure override(BridgeBase) returns (uint256) { + ) public pure override (BridgeBase) returns (uint256) { return _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address); } diff --git a/src/bridges/yearn/YearnBridge.sol b/src/bridges/yearn/YearnBridge.sol index c0d80e01d..04c9db651 100644 --- a/src/bridges/yearn/YearnBridge.sol +++ b/src/bridges/yearn/YearnBridge.sol @@ -109,7 +109,7 @@ contract YearnBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_auxData == 0) { if (_outputAssetA.assetType != AztecTypes.AztecAssetType.ERC20) { revert ErrorLib.InvalidOutputA(); @@ -192,7 +192,7 @@ contract YearnBridge is BridgeBase { AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint64 _auxData - ) public pure override(BridgeBase) returns (uint256) { + ) public pure override (BridgeBase) returns (uint256) { if (_auxData > 1) { revert ErrorLib.InvalidAuxData(); } diff --git a/src/gas/angle/AngleSLPGas.s.sol b/src/gas/angle/AngleSLPGas.s.sol index 042e33964..d2ee261ec 100644 --- a/src/gas/angle/AngleSLPGas.s.sol +++ b/src/gas/angle/AngleSLPGas.s.sol @@ -28,7 +28,7 @@ contract AngleMeasure is AngleSLPDeployment { AztecTypes.AztecAsset internal wethAsset; AztecTypes.AztecAsset internal sanWethAsset; - function setUp() public override(BaseDeployment) { + function setUp() public override (BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/erc4626/ERC4626Gas.s.sol b/src/gas/erc4626/ERC4626Gas.s.sol index e41a3f33b..941c4ea80 100644 --- a/src/gas/erc4626/ERC4626Gas.s.sol +++ b/src/gas/erc4626/ERC4626Gas.s.sol @@ -36,7 +36,7 @@ contract ERC4626Measure is ERC4626Deployment { AztecTypes.AztecAsset internal daiAsset; AztecTypes.AztecAsset internal wcDaiAsset; // ERC4626-Wrapped Compound Dai - function setUp() public override(BaseDeployment) { + function setUp() public override (BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/liquity/TroveBridgeGas.s.sol b/src/gas/liquity/TroveBridgeGas.s.sol index 4b5421ab8..dc87c53cb 100644 --- a/src/gas/liquity/TroveBridgeGas.s.sol +++ b/src/gas/liquity/TroveBridgeGas.s.sol @@ -26,7 +26,7 @@ contract TroveBridgeMeasure is LiquityTroveDeployment { AztecTypes.AztecAsset internal lusdAsset; AztecTypes.AztecAsset internal tbAsset; // Accounting token - function setUp() public override(BaseDeployment) { + function setUp() public override (BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/uniswap/UniswapGas.s.sol b/src/gas/uniswap/UniswapGas.s.sol index 33975c8a3..8637dc933 100644 --- a/src/gas/uniswap/UniswapGas.s.sol +++ b/src/gas/uniswap/UniswapGas.s.sol @@ -33,7 +33,7 @@ contract UniswapMeasure is UniswapDeployment { UniswapBridge.SplitPath internal emptySplitPath; - function setUp() public override(BaseDeployment) { + function setUp() public override (BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/test/bridges/erc4626/mocks/WETHVault.sol b/src/test/bridges/erc4626/mocks/WETHVault.sol index d75ea7399..cb5e4d484 100644 --- a/src/test/bridges/erc4626/mocks/WETHVault.sol +++ b/src/test/bridges/erc4626/mocks/WETHVault.sol @@ -10,7 +10,7 @@ contract WETHVault is ERC20("WETH vault", "vWETH"), ERC4626(IERC20Metadata(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)) { - function decimals() public pure override(ERC20, ERC4626) returns (uint8) { + function decimals() public pure override (ERC20, ERC4626) returns (uint8) { return 18; } } diff --git a/src/test/bridges/liquity/utils/MockPriceFeed.sol b/src/test/bridges/liquity/utils/MockPriceFeed.sol index 5df5f19b0..b1ea7c1a8 100644 --- a/src/test/bridges/liquity/utils/MockPriceFeed.sol +++ b/src/test/bridges/liquity/utils/MockPriceFeed.sol @@ -12,7 +12,7 @@ contract MockPriceFeed is IPriceFeed { lastGoodPrice = _price; } - function fetchPrice() external override(IPriceFeed) returns (uint256) { + function fetchPrice() external override (IPriceFeed) returns (uint256) { return lastGoodPrice; } } From c5fd3930d6af4f4dc93fc9933453ab41c2dfbba5 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Tue, 10 Jan 2023 14:38:34 -0500 Subject: [PATCH 65/65] retry fmt --- src/aztec/Subsidy.sol | 27 ++++++++----------- src/bridges/angle/AngleSLPBridge.sol | 4 +-- src/bridges/base/BridgeBase.sol | 4 +-- src/bridges/curve/CurveStEthBridge.sol | 2 +- src/bridges/dca/BiDCABridge.sol | 4 +-- src/bridges/dca/UniswapDCABridge.sol | 2 +- src/bridges/donation/DonationBridge.sol | 2 +- src/bridges/element/ElementBridge.sol | 4 +-- src/bridges/erc4626/ERC4626Bridge.sol | 4 +-- src/bridges/example/ExampleBridge.sol | 4 +-- src/bridges/lido/LidoBridge.sol | 2 +- src/bridges/liquity/StabilityPoolBridge.sol | 4 +-- src/bridges/liquity/StakingBridge.sol | 4 +-- src/bridges/liquity/TroveBridge.sol | 6 ++--- src/bridges/nft-basic/NFTVault.sol | 2 +- src/bridges/registry/AddressRegistry.sol | 2 +- src/bridges/uniswap/UniswapBridge.sol | 4 +-- src/bridges/yearn/YearnBridge.sol | 4 +-- src/gas/angle/AngleSLPGas.s.sol | 2 +- src/gas/erc4626/ERC4626Gas.s.sol | 2 +- src/gas/liquity/TroveBridgeGas.s.sol | 2 +- src/gas/uniswap/UniswapGas.s.sol | 2 +- src/test/bridges/erc4626/mocks/WETHVault.sol | 2 +- .../bridges/liquity/utils/MockPriceFeed.sol | 2 +- 24 files changed, 46 insertions(+), 51 deletions(-) diff --git a/src/aztec/Subsidy.sol b/src/aztec/Subsidy.sol index 2e3566e59..4d9bf2a78 100644 --- a/src/aztec/Subsidy.sol +++ b/src/aztec/Subsidy.sol @@ -60,7 +60,7 @@ contract Subsidy is ISubsidy { // @dev Using min possible `msg.value` upon subsidizing in order to limit possibility of front running attacks // --> e.g. attacker front-running real subsidy tx by sending 1 wei value tx making the real one revert - uint256 public constant override (ISubsidy) MIN_SUBSIDY_VALUE = 1e17; + uint256 public constant override(ISubsidy) MIN_SUBSIDY_VALUE = 1e17; // address bridge => uint256 criteria => Subsidy subsidy mapping(address => mapping(uint256 => Subsidy)) public subsidies; @@ -73,7 +73,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary The address of the beneficiary to query * @return The amount of claimable ETH for `_beneficiary` */ - function claimableAmount(address _beneficiary) external view override (ISubsidy) returns (uint256) { + function claimableAmount(address _beneficiary) external view override(ISubsidy) returns (uint256) { return beneficiaries[_beneficiary].claimable; } @@ -82,7 +82,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary The address of the beneficiary to check * @return True if the `_beneficiary` is registered, false otherwise */ - function isRegistered(address _beneficiary) external view override (ISubsidy) returns (bool) { + function isRegistered(address _beneficiary) external view override(ISubsidy) returns (bool) { return beneficiaries[_beneficiary].registered; } @@ -92,12 +92,7 @@ contract Subsidy is ISubsidy { * @param _criteria The criteria of the subsidy * @return The subsidy data object */ - function getSubsidy(address _bridge, uint256 _criteria) - external - view - override (ISubsidy) - returns (Subsidy memory) - { + function getSubsidy(address _bridge, uint256 _criteria) external view override(ISubsidy) returns (Subsidy memory) { return subsidies[_bridge][_criteria]; } @@ -114,7 +109,7 @@ contract Subsidy is ISubsidy { uint256[] calldata _criteria, uint32[] calldata _gasUsage, uint32[] calldata _minGasPerMinute - ) external override (ISubsidy) { + ) external override(ISubsidy) { uint256 criteriasLength = _criteria.length; if (criteriasLength != _gasUsage.length || criteriasLength != _minGasPerMinute.length) { revert ArrayLengthsDoNotMatch(); @@ -137,7 +132,7 @@ contract Subsidy is ISubsidy { * IDefiBridge.convert(...) function to be as predictable as possible. If the cost is too variable users would * overpay since RollupProcessor works with constant gas limits. */ - function registerBeneficiary(address _beneficiary) external override (ISubsidy) { + function registerBeneficiary(address _beneficiary) external override(ISubsidy) { beneficiaries[_beneficiary].registered = true; emit BeneficiaryRegistered(_beneficiary); } @@ -152,7 +147,7 @@ contract Subsidy is ISubsidy { * 3) subsidy.gasUsage not set: `subsidy.gasUsage` == 0, * 4) ETH value sent too low: `msg.value` < `MIN_SUBSIDY_VALUE`. */ - function subsidize(address _bridge, uint256 _criteria, uint32 _gasPerMinute) external payable override (ISubsidy) { + function subsidize(address _bridge, uint256 _criteria, uint32 _gasPerMinute) external payable override(ISubsidy) { if (msg.value < MIN_SUBSIDY_VALUE) { revert SubsidyTooLow(); } @@ -185,7 +180,7 @@ contract Subsidy is ISubsidy { * @param _criteria A value defining the specific bridge call to subsidize * @dev Reverts if `available` is 0. */ - function topUp(address _bridge, uint256 _criteria) external payable override (ISubsidy) { + function topUp(address _bridge, uint256 _criteria) external payable override(ISubsidy) { // Caching subsidy in order to minimize number of SLOADs and SSTOREs Subsidy memory sub = subsidies[_bridge][_criteria]; @@ -207,7 +202,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary Address which is going to receive the subsidy * @return subsidy ETH amount which was added to the `_beneficiary` claimable balance */ - function claimSubsidy(uint256 _criteria, address _beneficiary) external override (ISubsidy) returns (uint256) { + function claimSubsidy(uint256 _criteria, address _beneficiary) external override(ISubsidy) returns (uint256) { if (_beneficiary == address(0)) { return 0; } @@ -250,7 +245,7 @@ contract Subsidy is ISubsidy { * @param _beneficiary Address which is going to receive the subsidy * @return - ETH amount which was sent to the `_beneficiary` */ - function withdraw(address _beneficiary) external override (ISubsidy) returns (uint256) { + function withdraw(address _beneficiary) external override(ISubsidy) returns (uint256) { uint256 withdrawableBalance = beneficiaries[_beneficiary].claimable; // Immediately updating the balance to avoid re-entrancy attack beneficiaries[_beneficiary].claimable = 0; @@ -284,7 +279,7 @@ contract Subsidy is ISubsidy { */ function setGasUsageAndMinGasPerMinute(uint256 _criteria, uint32 _gasUsage, uint32 _minGasPerMinute) public - override (ISubsidy) + override(ISubsidy) { // Loading `sub` first in order to not overwrite `sub.available` in case this function was already called // and a subsidy was set. diff --git a/src/bridges/angle/AngleSLPBridge.sol b/src/bridges/angle/AngleSLPBridge.sol index c75c333e3..7b8f1ad00 100644 --- a/src/bridges/angle/AngleSLPBridge.sol +++ b/src/bridges/angle/AngleSLPBridge.sol @@ -89,7 +89,7 @@ contract AngleSLPBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { address inputAssetA; address outputAssetA; @@ -144,7 +144,7 @@ contract AngleSLPBridge is BridgeBase { AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint64 _auxData - ) public pure override (BridgeBase) returns (uint256) { + ) public pure override(BridgeBase) returns (uint256) { if (_auxData > 1) { revert ErrorLib.InvalidAuxData(); } diff --git a/src/bridges/base/BridgeBase.sol b/src/bridges/base/BridgeBase.sol index 21a227700..235dc01bb 100644 --- a/src/bridges/base/BridgeBase.sol +++ b/src/bridges/base/BridgeBase.sol @@ -39,7 +39,7 @@ abstract contract BridgeBase is IDefiBridge { uint256, uint64, address - ) external payable virtual override (IDefiBridge) returns (uint256, uint256, bool) { + ) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) { revert MissingImplementation(); } @@ -50,7 +50,7 @@ abstract contract BridgeBase is IDefiBridge { AztecTypes.AztecAsset calldata, uint256, uint64 - ) external payable virtual override (IDefiBridge) returns (uint256, uint256, bool) { + ) external payable virtual override(IDefiBridge) returns (uint256, uint256, bool) { revert ErrorLib.AsyncDisabled(); } diff --git a/src/bridges/curve/CurveStEthBridge.sol b/src/bridges/curve/CurveStEthBridge.sol index 99c9019e5..4beda802d 100644 --- a/src/bridges/curve/CurveStEthBridge.sol +++ b/src/bridges/curve/CurveStEthBridge.sol @@ -71,7 +71,7 @@ contract CurveStEthBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { bool isETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH; bool isWstETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 && _inputAssetA.erc20Address == address(WRAPPED_STETH); diff --git a/src/bridges/dca/BiDCABridge.sol b/src/bridges/dca/BiDCABridge.sol index d798db9fc..b8701aab8 100644 --- a/src/bridges/dca/BiDCABridge.sol +++ b/src/bridges/dca/BiDCABridge.sol @@ -243,7 +243,7 @@ abstract contract BiDCABridge is BridgeBase { uint256 _interactionNonce, uint64 _numTicks, address - ) external payable override (BridgeBase) onlyRollup returns (uint256, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256, uint256, bool) { address inputAssetAddress = _inputAssetA.erc20Address; address outputAssetAddress = _outputAssetA.erc20Address; @@ -289,7 +289,7 @@ abstract contract BiDCABridge is BridgeBase { external payable virtual - override (BridgeBase) + override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool interactionComplete) { diff --git a/src/bridges/dca/UniswapDCABridge.sol b/src/bridges/dca/UniswapDCABridge.sol index 6d6ebcf7f..b4e0a2c02 100644 --- a/src/bridges/dca/UniswapDCABridge.sol +++ b/src/bridges/dca/UniswapDCABridge.sol @@ -109,7 +109,7 @@ contract UniswapDCABridge is BiDCABridge { * @dev Reverts if the price is stale or negative * @return Price */ - function getPrice() public virtual override (BiDCABridge) returns (uint256) { + function getPrice() public virtual override(BiDCABridge) returns (uint256) { (, int256 answer,,,) = ORACLE.latestRoundData(); if (answer < 0) { revert NegativePrice(); diff --git a/src/bridges/donation/DonationBridge.sol b/src/bridges/donation/DonationBridge.sol index ef106e66e..da274e89f 100644 --- a/src/bridges/donation/DonationBridge.sol +++ b/src/bridges/donation/DonationBridge.sol @@ -57,7 +57,7 @@ contract DonationBridge is BridgeBase { uint256, uint64 _auxData, address - ) external payable override (BridgeBase) onlyRollup returns (uint256, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256, uint256, bool) { address receiver = donees[_auxData]; if (receiver == address(0)) { diff --git a/src/bridges/element/ElementBridge.sol b/src/bridges/element/ElementBridge.sol index a703b890e..2a7b5603b 100644 --- a/src/bridges/element/ElementBridge.sol +++ b/src/bridges/element/ElementBridge.sol @@ -428,7 +428,7 @@ contract ElementBridge is BridgeBase { ) external payable - override (BridgeBase) + override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { @@ -602,7 +602,7 @@ contract ElementBridge is BridgeBase { ) external payable - override (BridgeBase) + override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool interactionCompleted) { diff --git a/src/bridges/erc4626/ERC4626Bridge.sol b/src/bridges/erc4626/ERC4626Bridge.sol index 2e9bea983..47d7e372c 100644 --- a/src/bridges/erc4626/ERC4626Bridge.sol +++ b/src/bridges/erc4626/ERC4626Bridge.sol @@ -87,7 +87,7 @@ contract ERC4626Bridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { address inputToken = _inputAssetA.erc20Address; address outputToken = _outputAssetA.erc20Address; @@ -131,7 +131,7 @@ contract ERC4626Bridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public pure override (BridgeBase) returns (uint256) { + ) public pure override(BridgeBase) returns (uint256) { return _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address); } diff --git a/src/bridges/example/ExampleBridge.sol b/src/bridges/example/ExampleBridge.sol index 227f57655..0ee7aed18 100644 --- a/src/bridges/example/ExampleBridge.sol +++ b/src/bridges/example/ExampleBridge.sol @@ -59,7 +59,7 @@ contract ExampleBridge is BridgeBase { uint256, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { // Check the input asset is ERC20 if (_inputAssetA.assetType != AztecTypes.AztecAssetType.ERC20) revert ErrorLib.InvalidInputA(); if (_outputAssetA.erc20Address != _inputAssetA.erc20Address) revert ErrorLib.InvalidOutputA(); @@ -86,7 +86,7 @@ contract ExampleBridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public view override (BridgeBase) returns (uint256) { + ) public view override(BridgeBase) returns (uint256) { return uint256(keccak256(abi.encodePacked(_inputAssetA.erc20Address, _outputAssetA.erc20Address))); } } diff --git a/src/bridges/lido/LidoBridge.sol b/src/bridges/lido/LidoBridge.sol index ea4b3404b..a3e29db3a 100644 --- a/src/bridges/lido/LidoBridge.sol +++ b/src/bridges/lido/LidoBridge.sol @@ -56,7 +56,7 @@ contract LidoBridge is BridgeBase { uint256 _interactionNonce, uint64, address - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool isAsync) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool isAsync) { bool isETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ETH; bool isWstETHInput = _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 && _inputAssetA.erc20Address == address(WRAPPED_STETH); diff --git a/src/bridges/liquity/StabilityPoolBridge.sol b/src/bridges/liquity/StabilityPoolBridge.sol index ef33c1706..fb9e1e4e8 100644 --- a/src/bridges/liquity/StabilityPoolBridge.sol +++ b/src/bridges/liquity/StabilityPoolBridge.sol @@ -113,7 +113,7 @@ contract StabilityPoolBridge is BridgeBase, ERC20("StabilityPoolBridge", "SPB") uint256, uint64 _auxData, address - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_inputAssetA.erc20Address == LUSD && _outputAssetA.erc20Address == address(this)) { // Deposit // Provides LUSD to the pool and claim rewards. @@ -151,7 +151,7 @@ contract StabilityPoolBridge is BridgeBase, ERC20("StabilityPoolBridge", "SPB") /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override (ERC20) returns (uint256) { + function totalSupply() public view override(ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/liquity/StakingBridge.sol b/src/bridges/liquity/StakingBridge.sol index f32fc44c3..3fbd3ec70 100644 --- a/src/bridges/liquity/StakingBridge.sol +++ b/src/bridges/liquity/StakingBridge.sol @@ -104,7 +104,7 @@ contract StakingBridge is BridgeBase, ERC20("StakingBridge", "SB") { uint256, uint64 _auxData, address - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_inputAssetA.erc20Address == LQTY && _outputAssetA.erc20Address == address(this)) { // Deposit // Stake and claim rewards @@ -141,7 +141,7 @@ contract StakingBridge is BridgeBase, ERC20("StakingBridge", "SB") { /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override (ERC20) returns (uint256) { + function totalSupply() public view override(ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/liquity/TroveBridge.sol b/src/bridges/liquity/TroveBridge.sol index de8fbe235..79daf18d5 100644 --- a/src/bridges/liquity/TroveBridge.sol +++ b/src/bridges/liquity/TroveBridge.sol @@ -193,7 +193,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool) { Status troveStatus = Status(TROVE_MANAGER.getTroveStatus(address(this))); uint256 subsidyCriteria; @@ -283,7 +283,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { // @dev See _repayWithCollateral(...) method for more information about how this callback is entered. function uniswapV3SwapCallback(int256 _amount0Delta, int256 _amount1Delta, bytes calldata _data) external - override (IUniswapV3SwapCallback) + override(IUniswapV3SwapCallback) { // Swaps entirely within 0-liquidity regions are not supported if (_amount0Delta <= 0 && _amount1Delta <= 0) revert InvalidDeltaAmounts(); @@ -353,7 +353,7 @@ contract TroveBridge is BridgeBase, ERC20, Ownable, IUniswapV3SwapCallback { /** * @dev See {IERC20-totalSupply}. */ - function totalSupply() public view override (ERC20) returns (uint256) { + function totalSupply() public view override(ERC20) returns (uint256) { return super.totalSupply() - DUST; } diff --git a/src/bridges/nft-basic/NFTVault.sol b/src/bridges/nft-basic/NFTVault.sol index dec468119..d37ddbe28 100644 --- a/src/bridges/nft-basic/NFTVault.sol +++ b/src/bridges/nft-basic/NFTVault.sol @@ -68,7 +68,7 @@ contract NFTVault is BridgeBase { ) external payable - override (BridgeBase) + override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256 outputValueB, bool isAsync) { diff --git a/src/bridges/registry/AddressRegistry.sol b/src/bridges/registry/AddressRegistry.sol index cc3b68043..d7bad34fc 100644 --- a/src/bridges/registry/AddressRegistry.sol +++ b/src/bridges/registry/AddressRegistry.sol @@ -48,7 +48,7 @@ contract AddressRegistry is BridgeBase { uint256, uint64, address - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if ( _inputAssetA.assetType == AztecTypes.AztecAssetType.NOT_USED || _inputAssetA.assetType == AztecTypes.AztecAssetType.ERC20 diff --git a/src/bridges/uniswap/UniswapBridge.sol b/src/bridges/uniswap/UniswapBridge.sol index e1c6acebd..5c3bdc6c5 100644 --- a/src/bridges/uniswap/UniswapBridge.sol +++ b/src/bridges/uniswap/UniswapBridge.sol @@ -187,7 +187,7 @@ contract UniswapBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { // Accumulate subsidy to _rollupBeneficiary SUBSIDY.claimSubsidy( _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address), _rollupBeneficiary @@ -319,7 +319,7 @@ contract UniswapBridge is BridgeBase { AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint64 - ) public pure override (BridgeBase) returns (uint256) { + ) public pure override(BridgeBase) returns (uint256) { return _computeCriteria(_inputAssetA.erc20Address, _outputAssetA.erc20Address); } diff --git a/src/bridges/yearn/YearnBridge.sol b/src/bridges/yearn/YearnBridge.sol index 04c9db651..c0d80e01d 100644 --- a/src/bridges/yearn/YearnBridge.sol +++ b/src/bridges/yearn/YearnBridge.sol @@ -109,7 +109,7 @@ contract YearnBridge is BridgeBase { uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary - ) external payable override (BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { + ) external payable override(BridgeBase) onlyRollup returns (uint256 outputValueA, uint256, bool) { if (_auxData == 0) { if (_outputAssetA.assetType != AztecTypes.AztecAssetType.ERC20) { revert ErrorLib.InvalidOutputA(); @@ -192,7 +192,7 @@ contract YearnBridge is BridgeBase { AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint64 _auxData - ) public pure override (BridgeBase) returns (uint256) { + ) public pure override(BridgeBase) returns (uint256) { if (_auxData > 1) { revert ErrorLib.InvalidAuxData(); } diff --git a/src/gas/angle/AngleSLPGas.s.sol b/src/gas/angle/AngleSLPGas.s.sol index d2ee261ec..042e33964 100644 --- a/src/gas/angle/AngleSLPGas.s.sol +++ b/src/gas/angle/AngleSLPGas.s.sol @@ -28,7 +28,7 @@ contract AngleMeasure is AngleSLPDeployment { AztecTypes.AztecAsset internal wethAsset; AztecTypes.AztecAsset internal sanWethAsset; - function setUp() public override (BaseDeployment) { + function setUp() public override(BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/erc4626/ERC4626Gas.s.sol b/src/gas/erc4626/ERC4626Gas.s.sol index 941c4ea80..e41a3f33b 100644 --- a/src/gas/erc4626/ERC4626Gas.s.sol +++ b/src/gas/erc4626/ERC4626Gas.s.sol @@ -36,7 +36,7 @@ contract ERC4626Measure is ERC4626Deployment { AztecTypes.AztecAsset internal daiAsset; AztecTypes.AztecAsset internal wcDaiAsset; // ERC4626-Wrapped Compound Dai - function setUp() public override (BaseDeployment) { + function setUp() public override(BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/liquity/TroveBridgeGas.s.sol b/src/gas/liquity/TroveBridgeGas.s.sol index dc87c53cb..4b5421ab8 100644 --- a/src/gas/liquity/TroveBridgeGas.s.sol +++ b/src/gas/liquity/TroveBridgeGas.s.sol @@ -26,7 +26,7 @@ contract TroveBridgeMeasure is LiquityTroveDeployment { AztecTypes.AztecAsset internal lusdAsset; AztecTypes.AztecAsset internal tbAsset; // Accounting token - function setUp() public override (BaseDeployment) { + function setUp() public override(BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/gas/uniswap/UniswapGas.s.sol b/src/gas/uniswap/UniswapGas.s.sol index 8637dc933..33975c8a3 100644 --- a/src/gas/uniswap/UniswapGas.s.sol +++ b/src/gas/uniswap/UniswapGas.s.sol @@ -33,7 +33,7 @@ contract UniswapMeasure is UniswapDeployment { UniswapBridge.SplitPath internal emptySplitPath; - function setUp() public override (BaseDeployment) { + function setUp() public override(BaseDeployment) { super.setUp(); address defiProxy = IRead(ROLLUP_PROCESSOR).defiBridgeProxy(); diff --git a/src/test/bridges/erc4626/mocks/WETHVault.sol b/src/test/bridges/erc4626/mocks/WETHVault.sol index cb5e4d484..d75ea7399 100644 --- a/src/test/bridges/erc4626/mocks/WETHVault.sol +++ b/src/test/bridges/erc4626/mocks/WETHVault.sol @@ -10,7 +10,7 @@ contract WETHVault is ERC20("WETH vault", "vWETH"), ERC4626(IERC20Metadata(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)) { - function decimals() public pure override (ERC20, ERC4626) returns (uint8) { + function decimals() public pure override(ERC20, ERC4626) returns (uint8) { return 18; } } diff --git a/src/test/bridges/liquity/utils/MockPriceFeed.sol b/src/test/bridges/liquity/utils/MockPriceFeed.sol index b1ea7c1a8..5df5f19b0 100644 --- a/src/test/bridges/liquity/utils/MockPriceFeed.sol +++ b/src/test/bridges/liquity/utils/MockPriceFeed.sol @@ -12,7 +12,7 @@ contract MockPriceFeed is IPriceFeed { lastGoodPrice = _price; } - function fetchPrice() external override (IPriceFeed) returns (uint256) { + function fetchPrice() external override(IPriceFeed) returns (uint256) { return lastGoodPrice; } }