From dad9cf2d00c18cf655bee97ef4c118a464553684 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Fri, 3 Nov 2023 10:56:31 -0400 Subject: [PATCH 01/15] feat: update bridge owner and README as well as add missing natspec --- scripts/DeployBridges.s.sol | 7 ++++--- src/bridges/AavePolEthERC20Bridge.sol | 4 ++++ src/bridges/README.md | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/DeployBridges.s.sol b/scripts/DeployBridges.s.sol index 84a87814b..c8408744a 100644 --- a/scripts/DeployBridges.s.sol +++ b/scripts/DeployBridges.s.sol @@ -3,18 +3,19 @@ pragma solidity ^0.8.0; import {EthereumScript, PolygonScript} from 'src/ScriptUtils.sol'; import {AavePolEthERC20Bridge} from 'src/bridges/AavePolEthERC20Bridge.sol'; -import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {GovernanceV3Polygon} from 'aave-address-book/GovernanceV3Polygon.sol'; contract DeployEthereum is EthereumScript { function run() external broadcast { bytes32 salt = 'Aave Treasury Bridge'; - new AavePolEthERC20Bridge{salt: salt}(AaveGovernanceV2.SHORT_EXECUTOR); + new AavePolEthERC20Bridge{salt: salt}(GovernanceV3Ethereum.EXECUTOR_LVL_1); } } contract DeployPolygon is PolygonScript { function run() external broadcast { bytes32 salt = 'Aave Treasury Bridge'; - new AavePolEthERC20Bridge{salt: salt}(AaveGovernanceV2.POLYGON_BRIDGE_EXECUTOR); + new AavePolEthERC20Bridge{salt: salt}(GovernanceV3Polygon.EXECUTOR_LVL_1); } } diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index 822dbd524..ed7ba97d5 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -85,6 +85,10 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { emit WithdrawToCollector(token, balance); } + /* + * Returns the address of the address who can rescue funds in this contract + * @returns address + */ function whoCanRescue() public view override returns (address) { return owner(); } diff --git a/src/bridges/README.md b/src/bridges/README.md index 80845f34d..4142e2f06 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -43,6 +43,8 @@ And the generated proof: https://proof-generator.polygon.technology/api/v1/matic The result is the bytes data that is later passed to `exit()`. +If doing multiple burns in one transaction, each has to be processed individually via exit. To get a specific logIndex to generate the correct proof when doing multiple, you can append to the API URL `&tokenIndex=[INDEX_OF_TARGET_LOG]`. + ## Deployed Addresses Mainnet: From 229dbb070ad2180649a054adea72026cf5750f9e Mon Sep 17 00:00:00 2001 From: efecarranza Date: Mon, 6 Nov 2023 11:19:58 -0500 Subject: [PATCH 02/15] chore: update inherit doc --- src/bridges/AavePolEthERC20Bridge.sol | 26 ++++---------------------- src/bridges/IAavePolEthERC20Bridge.sol | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index ed7ba97d5..56b0e4563 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -44,13 +44,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { _transferOwnership(_owner); } - /* - * This function withdraws an ERC20 token from Polygon to Mainnet. exit() needs - * to be called on mainnet with the corresponding burnProof in order to complete. - * @notice Polygon only. Function will revert if called from other network. - * @param token Polygon address of ERC20 token to withdraw - * @param amount Amount of tokens to withdraw - */ + /// @inheritdoc IAavePolEthERC20Bridge function bridge(address token, uint256 amount) external onlyOwner { if (block.chainid != ChainIds.POLYGON) revert InvalidChain(); @@ -58,12 +52,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { emit Bridge(token, amount); } - /* - * This function completes the withdrawal process from Polygon to Mainnet. - * Burn proof is generated via API. Please see README.md - * @notice Mainnet only. Function will revert if called from other network. - * @param burnProof Burn proof generated via API. - */ + /// @inheritdoc IAavePolEthERC20Bridge function exit(bytes calldata burnProof) external { if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); @@ -71,11 +60,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { emit Exit(); } - /* - * Withdraws tokens on Mainnet contract to Aave V3 Collector. - * @notice Mainnet only. Function will revert if called from other network. - * @param token Mainnet address of token to withdraw to Collector - */ + /// @inheritdoc IAavePolEthERC20Bridge function withdrawToCollector(address token) external { if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); @@ -85,10 +70,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { emit WithdrawToCollector(token, balance); } - /* - * Returns the address of the address who can rescue funds in this contract - * @returns address - */ + /// @inheritdoc Rescuable function whoCanRescue() public view override returns (address) { return owner(); } diff --git a/src/bridges/IAavePolEthERC20Bridge.sol b/src/bridges/IAavePolEthERC20Bridge.sol index 6805fd492..348d976ff 100644 --- a/src/bridges/IAavePolEthERC20Bridge.sol +++ b/src/bridges/IAavePolEthERC20Bridge.sol @@ -3,9 +3,27 @@ pragma solidity ^0.8.0; interface IAavePolEthERC20Bridge { + /* + * This function withdraws an ERC20 token from Polygon to Mainnet. exit() needs + * to be called on mainnet with the corresponding burnProof in order to complete. + * @notice Polygon only. Function will revert if called from other network. + * @param token Polygon address of ERC20 token to withdraw + * @param amount Amount of tokens to withdraw + */ function bridge(address token, uint256 amount) external; + /* + * This function completes the withdrawal process from Polygon to Mainnet. + * Burn proof is generated via API. Please see README.md + * @notice Mainnet only. Function will revert if called from other network. + * @param burnProof Burn proof generated via API. + */ function exit(bytes calldata burnProof) external; + /* + * Withdraws tokens on Mainnet contract to Aave V3 Collector. + * @notice Mainnet only. Function will revert if called from other network. + * @param token Mainnet address of token to withdraw to Collector + */ function withdrawToCollector(address token) external; } From 6e17a2690b0e744f4fddf6c0a58511765ffb54eb Mon Sep 17 00:00:00 2001 From: efecarranza Date: Tue, 7 Nov 2023 14:59:00 -0500 Subject: [PATCH 03/15] feat: add support for multiple proof burns --- src/bridges/AavePolEthERC20Bridge.sol | 15 +++- src/bridges/IAavePolEthERC20Bridge.sol | 8 +++ tests/bridges/AavePolEthERC20BridgeTest.t.sol | 68 +++++++++++++++++-- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index 56b0e4563..6f2a33825 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -34,7 +34,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { error InvalidChain(); - event Exit(); + event Exit(bytes proof); event Bridge(address token, uint256 amount); event WithdrawToCollector(address token, uint256 amount); @@ -57,7 +57,18 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); IRootChainManager(ROOT_CHAIN_MANAGER).exit(burnProof); - emit Exit(); + emit Exit(burnProof); + } + + /// @inheritdoc IAavePolEthERC20Bridge + function exit(bytes[] calldata burnProofs) external { + if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); + + uint256 proofsLength = burnProofs.length; + for (uint256 i = 0; i < proofsLength; ++i) { + IRootChainManager(ROOT_CHAIN_MANAGER).exit(burnProofs[i]); + emit Exit(burnProofs[i]); + } } /// @inheritdoc IAavePolEthERC20Bridge diff --git a/src/bridges/IAavePolEthERC20Bridge.sol b/src/bridges/IAavePolEthERC20Bridge.sol index 348d976ff..d219c44be 100644 --- a/src/bridges/IAavePolEthERC20Bridge.sol +++ b/src/bridges/IAavePolEthERC20Bridge.sol @@ -20,6 +20,14 @@ interface IAavePolEthERC20Bridge { */ function exit(bytes calldata burnProof) external; + /* + * This function completes the withdrawal process from Polygon to Mainnet. + * Burn proofs are generated via API. Please see README.md + * @notice Mainnet only. Function will revert if called from other network. + * @param burnProofs Array of burn proofs generated via API. + */ + function exit(bytes[] calldata burnProofs) external; + /* * Withdraws tokens on Mainnet contract to Aave V3 Collector. * @notice Mainnet only. Function will revert if called from other network. diff --git a/tests/bridges/AavePolEthERC20BridgeTest.t.sol b/tests/bridges/AavePolEthERC20BridgeTest.t.sol index 1e84c7e60..5290cb3a6 100644 --- a/tests/bridges/AavePolEthERC20BridgeTest.t.sol +++ b/tests/bridges/AavePolEthERC20BridgeTest.t.sol @@ -6,9 +6,12 @@ import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {AaveV3Ethereum, AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol'; import {AaveV2Polygon, AaveV2PolygonAssets} from 'aave-address-book/AaveV2Polygon.sol'; import {AaveV3Polygon, AaveV3PolygonAssets} from 'aave-address-book/AaveV3Polygon.sol'; -import {AaveGovernanceV2} from 'aave-address-book/AaveGovernanceV2.sol'; +import {MiscEthereum} from 'aave-address-book/MiscEthereum.sol'; +import {GovernanceV3Ethereum} from 'aave-address-book/GovernanceV3Ethereum.sol'; +import {GovernanceV3Polygon} from 'aave-address-book/GovernanceV3Polygon.sol'; import {AavePolEthERC20Bridge} from '../../src/bridges/AavePolEthERC20Bridge.sol'; +import {IAavePolEthERC20Bridge} from '../../src/bridges/IAavePolEthERC20Bridge.sol'; /** * @dev Tests for AavePolEthERC20Bridge @@ -54,7 +57,7 @@ contract BridgeTest is AavePolEthERC20BridgeTest { IERC20(AaveV3PolygonAssets.USDC_UNDERLYING).transfer(address(bridgePolygon), amount); vm.stopPrank(); - bridgePolygon.transferOwnership(AaveGovernanceV2.POLYGON_BRIDGE_EXECUTOR); + bridgePolygon.transferOwnership(GovernanceV3Polygon.EXECUTOR_LVL_1); vm.expectRevert('Ownable: caller is not the owner'); bridgePolygon.bridge(AaveV3PolygonAssets.USDC_UNDERLYING, amount); @@ -69,9 +72,9 @@ contract BridgeTest is AavePolEthERC20BridgeTest { IERC20(AaveV3PolygonAssets.USDC_UNDERLYING).transfer(address(bridgePolygon), amount); vm.stopPrank(); - bridgePolygon.transferOwnership(AaveGovernanceV2.POLYGON_BRIDGE_EXECUTOR); + bridgePolygon.transferOwnership(GovernanceV3Polygon.EXECUTOR_LVL_1); - vm.startPrank(AaveGovernanceV2.POLYGON_BRIDGE_EXECUTOR); + vm.startPrank(GovernanceV3Polygon.EXECUTOR_LVL_1); vm.expectEmit(); emit Bridge(AaveV3PolygonAssets.USDC_UNDERLYING, amount); bridgePolygon.bridge(AaveV3PolygonAssets.USDC_UNDERLYING, amount); @@ -102,7 +105,10 @@ contract EmergencyTokenTransfer is AavePolEthERC20BridgeTest { IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).transfer(address(bridgePolygon), balAmount); vm.stopPrank(); - assertEq(IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(bridgePolygon)), balAmount); + assertEq( + IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(bridgePolygon)), + balAmount + ); uint256 initialCollectorBalBalance = IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf( address(AaveV2Polygon.COLLECTOR) @@ -181,6 +187,35 @@ contract ExitTest is AavePolEthERC20BridgeTest { } } +/* + * No good way of testing the full flow as proof is generated via API 30-90 minutes after the + * bridge() function is called on Polygon. + */ +contract ExitMultipleTest is AavePolEthERC20BridgeTest { + function test_revertsIf_invalidChain() public { + vm.selectFork(polygonFork); + + bytes[] memory proofs = new bytes[](1); + proofs[0] = new bytes(0); + + vm.expectRevert(AavePolEthERC20Bridge.InvalidChain.selector); + bridgeMainnet.exit(proofs); + } + + function test_revertsIf_proofAlreadyProcessed() public { + vm.selectFork(mainnetFork); + + bytes + memory burnProof = hex'f90b7f841d64b820b901605a3ebbdce0b458c848c75ece30aebdc7f404de9f42a1a1d2fff616f4681f8239a5727c70050724191597596befd50c2db26c8c13cc424292fb8dca25990eec222a5378609f41effc1b6f8370a2fa3bff9c1701b0d63108094bc6255a69ffbdd28cdc2237e927128485372aaad7d4164d37669d61d82add0bcb6b8fb1ab7726d81a766ee748222e6253d91038cb42b06614c20fda1f61ede914ee3971321a91ba9674397ca6114056014024786d3b74639d792036e10be9fcca25cc63df3e90e9ce68a4c38ebdd54385ed78e7003995b50975ea080eac5178729d59ffe8c39ba44dce41d776560d9f83de07337ba28cf16a69f99c3be4c8f5001825b11a3e49fb966bcc41e4b74e001be2248c2e7d8319fddb180775cdf18660fa475f8b84db41cefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e030e0542044c7c3e032f92fdf59c763bff5ec2b5c0b34323fff644d44074033f18402bf7ab28464d3b68aa0cb3e23ec4a01a3517fdb7d985bbcd704d8d243c4b6baac426457e5e2b9febad1a01ab4bd6b4a9aef048d60e20a15ad53347c92418591ac1bcafc493834c0b0bc37b9036802f9036401840184b1b4b9010000000200000000000000000008000000000000000000000000100000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000040008000000800000000000000000000100000000000000000000020000000000000000000800000000000000000180000010000004001041000000040000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000080000000000000000000004000000002000000000801000000000004000000000000000000120000000020000000008000000000000000000000000001000000000000200000000800100000f90258f89b942791bca1f2de4661ed88a30c99a7a9449aa84174f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000ca807a3e47684caee82fda347729788639ab9ee8a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000f4240f87994ca807a3e47684caee82fda347729788639ab9ee8e1a0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364b8400000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000f4240f9013d940000000000000000000000000000000000001010f884a04dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63a00000000000000000000000000000000000000000000000000000000000001010a00000000000000000000000002fb7d6beb9ad75c1ffd392681cc68171b8551107a00000000000000000000000009ead03f7136fc6b4bdb0780b00a1c14ae5a8b6d0b8a000000000000000000000000000000000000000000000000000047f88eb62fdf8000000000000000000000000000000000000000000000000f6299bdc7ee7898c000000000000000000000000000000000000000000000231bb90e991a999704a000000000000000000000000000000000000000000000000f6251c5393848b94000000000000000000000000000000000000000000000231bb95691a94fc6e42b90659f90656f8d1a0edd856137974cc770c8ff2f0ae9691f6c343a5c3ea042cf43226064241cb4b48a060098e59303c6f97eb4ee11a31d7ff224886f7ee97e47046ffc12ae2cb345607a08c1c9ddcde956a2188fecf78ac3ffe88c5300e39016cedbc726eaa480528f2d9a0af1a8f4ebb2c2f62619a683563a51fcf38e82d6213ad60506a1f4472145a3d52a06a5a57546f33675a2827617483ba12e200a7666f107115010549cc72ce933a5c808080a04b654e084485e25f10ab6e63905b7b0320f3da65ed062eee77511204089557af8080808080808080f90211a0d18ede4a1807a43ea2daf1f43d94127479f5a5406ba4d9e1e1820b9fabc23f1ca0ae8d8894a06c033da2ef24d0e4b7f4d985fea9e4a808d0616a93e17c7d5ca556a08a42f3eed60ecb787277f3534c848ac3e881be498993840a4c550764414c45e7a0db5ed558b0871c5828866ff7ff1cdb6b7b28cce715c74837c704308e4e85d8d8a0e00d8c69aee0605693c270aa8bd5e4c156bf6782952df288e8f3002963ad51d1a06568d90c67a2972365abd5f2606aa2529d39cb7bc23eb0a130d673080697d715a0747a3b807241f10bee3360edb4345a815328fb885c8e8f693e1af88503c41bc4a01767769f78e7f63f7142b0468c85a7a98aad577dd31044167c60e4d77e5d5ad2a09e8fddbe949014bb311de991cb543da9fb3104cf4db4f87e4e800911c1d99f7da0de90b23b0cf3a2685afd3b221a1660d8655212ca01c82c5680a81f807e2b3aada0281f75fda5226a1f34390b09765843e2af5a3644ba577a555431b7f2dcef2c86a094065d6acf8901d70605b0c198b0ff5df364efc232f6c536c7df5a7632b4a7bea0a32affd2aad98f44bce23eed618177c1a51cdd617ef72ec8be8d55bda90bf59fa099a19c0a99d4913f691877ce52612a1da389b99ab2a51c471346ee07575f0780a0b948b78e59be6f2a016c545d93ae7efdf615bf212bbdc1fa568bc2c96752c044a09e07bfdc8af384b3f2f1a65561bfd28ebd85d3f2abbfba13108d25a38a25a1cd80f9036c20b9036802f9036401840184b1b4b9010000000200000000000000000008000000000000000000000000100000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000040008000000800000000000000000000100000000000000000000020000000000000000000800000000000000000180000010000004001041000000040000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000080000000000000000000004000000002000000000801000000000004000000000000000000120000000020000000008000000000000000000000000001000000000000200000000800100000f90258f89b942791bca1f2de4661ed88a30c99a7a9449aa84174f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000ca807a3e47684caee82fda347729788639ab9ee8a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000f4240f87994ca807a3e47684caee82fda347729788639ab9ee8e1a0884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364b8400000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000f4240f9013d940000000000000000000000000000000000001010f884a04dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63a00000000000000000000000000000000000000000000000000000000000001010a00000000000000000000000002fb7d6beb9ad75c1ffd392681cc68171b8551107a00000000000000000000000009ead03f7136fc6b4bdb0780b00a1c14ae5a8b6d0b8a000000000000000000000000000000000000000000000000000047f88eb62fdf8000000000000000000000000000000000000000000000000f6299bdc7ee7898c000000000000000000000000000000000000000000000231bb90e991a999704a000000000000000000000000000000000000000000000000f6251c5393848b94000000000000000000000000000000000000000000000231bb95691a94fc6e4282003580'; + + bytes[] memory proofs = new bytes[](1); + proofs[0] = burnProof; + + vm.expectRevert('RootChainManager: EXIT_ALREADY_PROCESSED'); + bridgeMainnet.exit(proofs); + } +} + contract TransferOwnership is AavePolEthERC20BridgeTest { function test_revertsIf_invalidCaller() public { vm.startPrank(makeAddr('random-caller')); @@ -190,9 +225,30 @@ contract TransferOwnership is AavePolEthERC20BridgeTest { } function test_successful() public { - address newAdmin = AaveGovernanceV2.SHORT_EXECUTOR; + address newAdmin = GovernanceV3Ethereum.EXECUTOR_LVL_1; bridgeMainnet.transferOwnership(newAdmin); assertEq(newAdmin, bridgeMainnet.owner()); } } + +/// This is a real proof one block prior to when it happened, with the Bridge address of: 0xc928002904Ec475663A83063D492EA2aE09EbDA1 +contract ForkedBridgeTests is Test { + function test_successful() public { + vm.createSelectFork(vm.rpcUrl('mainnet'), 18485843); // One block before an actual exit + + bytes + memory burnProof = hex'f94429841f8686b0b90140ec08e37a4c09ebcde82a99bbe213e98dadc3847b25fa2e7957d1b3d90d5eebff1006486861f9479c3750bc16f0a4d910572fb1fdc024e1115073f9919dc8f1ad8599af3e900ef15593699a15a84065e846f1db007495206c63a4b95f1e38dec961e0bbdec9a4e0b0f4d16c2b903b6a8dc6d6496b44da85a6786b8e8340bd50bafca7f6ad0593680a9fc6b174695fa0af5cf6febcbdd92c2bcf1de0e6936ca40bf1e57da148c5ec50554fd3f8497d575ccd04bba9a40cfbd62adce41fe2d47ec9bfaadefdd88c6d32c9f0dbbb2eb97a48ab84eacaf6d548770d8d19f01af48f23ad4bbb8fec633d28c0b782808b5180fdc191a3b79ec6279cd17b95422317cb4f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af183009cfbada5b6455c4e1187b67758b694698dc7ce8de85a74f6fe285f0ebe38402f0b5ca84653f7f37a041ea33e7ca127e9dcf3da38d9d153de8712864adac2403cc819f1ec23cb0e387a0a169587c035b52f56223839b8fb88019059d3299687edda67f36c51f4fd06c0fb91fcdf91fca0183a2ef0bb901000200420020000800008000000040000400900000000100008300000080000100000000020000002000000200040000080002800000004000200003100004001100004000000000008020000a08000481000200080804110080030008000040004040000002100000000008000000080000000400000802009400c0141000000000000000840000000000200000000008020040000822004000440040002000002100011100800000002020800000000020082080000200a0000000080100014000000002000000100001002000020120000000800000000004124000000061000000000800040000000280000000000002000400000804000020000000100000f91ebff89b94357d51124f59836ded84c8a1730d72b749d8bc23f863a0bb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585ba0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a000000000000000000000000027f8d03b3a2196956ed754badc28d73be8830a6ea0000000000000000000000000000000000000000000000000005184a301f41195f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc9427f8d03b3a2196956ed754badc28d73be8830a6ef863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b840000000000000000000000000000000000000000000013da329b633647180000000000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000000000000000000000013da329b6336471800000f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc38380f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b840000000000000000000000000000000000000000000000204d12df5dc51c6da77000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc38380f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc94c4195d4060daeac44058ed668aa5efec50d77ff6f863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b84000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a00000000000000000000000000000000000000000000000000c9d8ca802c04a76f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b8400000000000000000000000000000000000000000000000000c9d8ca802c04a7600000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063b8a00000000000000000000000000000000000000000000bc4428ff25d5245e72c830000000000000000000000000000000000000000002f80c94c9ca324d9b145990000000000000000000000000000000000000000001e7c6e2036d5e2a5628b3200000000000000000000000000000000000000000366fb8ad9555a5e1baebe51000000000000000000000000000000000000000003874b6dbe3ec433d1b2fb37f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b948f3cf7ad23cd3cadbd9735aff958023239c6a063f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000027f8d03b3a2196956ed754badc28d73be8830a6ea0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000013da329b6336471800000f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000013da329b6336471800000f8bc9427f8d03b3a2196956ed754badc28d73be8830a6ef863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b840000000000000000000000000000000000000000000013da329b633647180000000000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000013da329b6336471800000f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a00000000000000000000000000000000000000000000000000bf117f1ff35aaa2f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b8400000000000000000000000000000000000000000000000000bf117f1ff35aaa2000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afb8a00000000000000000000000000000000000000000000000603e869f9450289e2c00000000000000000000000000000000000000000056368c96672550bfd7864d0000000000000000000000000000000000000000005fd07e54af1384c7481440000000000000000000000000000000000000000003ccb6fd0d85b250934abfee00000000000000000000000000000000000000000477de475fd95229353c433ff87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b94172370d5cd63279efa6d502dab29171933a610aff863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000003df8f92b7e798820ddcca2ebea7babda2c90c4ada0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f8bc943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b840000000000000000000000000000000000000000000000204d12df5dc51c6da77000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a000000000000000000000000000000000000000000000000000ce772a4f4e4308f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b84000000000000000000000000000000000000000000000000000ce772a4f4e4308000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3b8a000000000000000000000000000000000000000000008787373c577c1c258b0a80000000000000000000000000000000000000000003496b1bb9e79a4f34620b50000000000000000000000000000000000000000005df29b2a02800e654620b5000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd5070000000000000000000000000000000000000000050c2b7e22f9c35395d37b02f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b949a71012b13ca4d3d0cdc72a177df3ef03b0e76a3f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c4195d4060daeac44058ed668aa5efec50d77ff6a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f8bc94c4195d4060daeac44058ed668aa5efec50d77ff6f863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b84000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b948f3cf7ad23cd3cadbd9735aff958023239c6a063f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000013da329b6336471800000f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb8400000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063000000000000000000000000000000000000000000013da329b6336471800000f89b94172370d5cd63279efa6d502dab29171933a610aff863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb840000000000000000000000000172370d5cd63279efa6d502dab29171933a610af000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b949a71012b13ca4d3d0cdc72a177df3ef03b0e76a3f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb8400000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a300000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f8fb94dc9a35b16db4e126cfedc41322b3a36454b1f772f842a0f5efc4bb09a12b6c9561a7e7ab02938a72a4351316b473d574fdaaa89c43eb9aa0000000000000000000000000da98b308be8766501ec7fe3ed9a48efbd6c31a7bb8a000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f87b94da98b308be8766501ec7fe3ed9a48efbd6c31a7bf863a01d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec14250a00000000000000000000000000000000000000000000000000000000000000047a0000000000000000000000000000000000000000000000000000000000000000080f9015d9402777053d6764996e594c3e88af1d58d5363a2e6f884a0caacad83e47cc45c280d487ec84184eee2fa3b54ebaa393bda7549f13da228f6a00ba6f5a29753ee4861917fbae7122075257c5a8b702791ecdca09fd4abfb40e5a00000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000d9a31dc8347284a6bea9598d49d8dacbfd5774f1b8c00000000000000000000000000000000000000000000000000036fe68904af8cc00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000047f9013d940000000000000000000000000000000000001010f884a04dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63a00000000000000000000000000000000000000000000000000000000000001010a0000000000000000000000000d9a31dc8347284a6bea9598d49d8dacbfd5774f1a0000000000000000000000000bdbd4347b082d9d6bdf2da4555a37ce52a2e2120b8a000000000000000000000000000000000000000000000000001140015237d04970000000000000000000000000000000000000000000000234e3393093dd75603000000000000000000000000000000000000000000004578091978720a7a78fe0000000000000000000000000000000000000000000000234d1f92f41a5a516c0000000000000000000000000000000000000000000045780a2d78872df77d95b922bef922bbf8d1a02e1cded6745b2647ded60567ef904b1488a2202d8c10b4ce2a6325c5874e70a1a0d55f193383311082b88c376ae4c155d14c4795e78d01b57df7ac1b2a0953a3aba0d3fd23c69be1a376891333316a4d4915b16b1ba2837b7395eafd138470a8a9c2a00f728e4cd94c8946176f3bab3285d0a4cf675c745ded223eea13c1749373b406a0d4fde17a9a997d82a718d0109fbad0865ae0f676a6d9453ba25f7cc9f7440ffa808080a091014260b7c5e3e034c1bb93e5c56d876bbafc5e9c45bee246a09c4d778918268080808080808080f90211a0dc223d7d9d1f62a17d6755b3ea49a459fdc841677a4d6ea3c10ae9fe3b74cc85a0d4386c4f27e167dd5904a6829137d4a071b807360b41c33e508da83c16ef0dcaa0ee33d016d743f18fcd1d3f441204cb6c7bbc7f27c348f00a1525f625a90d5351a012e159719d02a9bedefc92ba3b14aab8548930b4d96c4273270307a822b167b2a00ee37834474bd26aa665f7ec5471b7e36ca46bd285e4672feacf8ee117aaeb11a0f553c892c39772cc4e15f3014c132cdc1eec574aeb61c78b488288f0f3d687dba05fc1ab2dcb80faa44e595225cf7c9f776cc0a94a03dee4f00c1aabd1101916d2a0027633218ce323577d192ba3fe4fbb16f5ea20d5ced6dc8ac5388ecd69377150a0b0c37b48b21deb48d3597313e9b6044164b58b665266a89b76ce30bd86d158c9a029465187eb0c9d84221a82b868b22a542f6c2b51a738fb9207daaf92a2f28a91a052f6b425918430b09a6c2dc7226e57420d6dc0175f75ccfd0cd125128b0d1acca01ba7c6113177eb50a6309262f9da68c025f040e8223cab0660614dd87a534891a0553953d0786a7ea5c12eadbb3efed3e4167421f1fcecd0839311ca41fb52ec35a09760e1282cb44a42da18a26f79049948043218067c570de23d2b59306d3b0da6a02f5030a870e23986e7fbb32bd4c50174c34f725089a50bde3298ac398080e696a06f2c7fde9db1e657aed7c92b969b53769c16bdf8ea8706f3e92854b2efc9601e80f91fd120b91fcdf91fca0183a2ef0bb901000200420020000800008000000040000400900000000100008300000080000100000000020000002000000200040000080002800000004000200003100004001100004000000000008020000a08000481000200080804110080030008000040004040000002100000000008000000080000000400000802009400c0141000000000000000840000000000200000000008020040000822004000440040002000002100011100800000002020800000000020082080000200a0000000080100014000000002000000100001002000020120000000800000000004124000000061000000000800040000000280000000000002000400000804000020000000100000f91ebff89b94357d51124f59836ded84c8a1730d72b749d8bc23f863a0bb123b5c06d5408bbea3c4fef481578175cfb432e3b482c6186f02ed9086585ba0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a000000000000000000000000027f8d03b3a2196956ed754badc28d73be8830a6ea0000000000000000000000000000000000000000000000000005184a301f41195f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc9427f8d03b3a2196956ed754badc28d73be8830a6ef863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b840000000000000000000000000000000000000000000013da329b633647180000000000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000000000000000000000013da329b6336471800000f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc38380f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b840000000000000000000000000000000000000000000000204d12df5dc51c6da77000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc38380f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a000058a56ea94653cdf4f152d227ace22d4c00ad99e2a43f58cb7d9e3feb295f2a00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f8bc94c4195d4060daeac44058ed668aa5efec50d77ff6f863a04beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772b84000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a00000000000000000000000000000000000000000000000000c9d8ca802c04a76f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b8400000000000000000000000000000000000000000000000000c9d8ca802c04a7600000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063b8a00000000000000000000000000000000000000000000bc4428ff25d5245e72c830000000000000000000000000000000000000000002f80c94c9ca324d9b145990000000000000000000000000000000000000000001e7c6e2036d5e2a5628b3200000000000000000000000000000000000000000366fb8ad9555a5e1baebe51000000000000000000000000000000000000000003874b6dbe3ec433d1b2fb37f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b948f3cf7ad23cd3cadbd9735aff958023239c6a063f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000027f8d03b3a2196956ed754badc28d73be8830a6ea0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000013da329b6336471800000f89b9427f8d03b3a2196956ed754badc28d73be8830a6ef863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000013da329b6336471800000f8bc9427f8d03b3a2196956ed754badc28d73be8830a6ef863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b840000000000000000000000000000000000000000000013da329b633647180000000000000000000000000000000000000000000000366fb8ad9555a5e1baebe51f8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a00000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000013da329b6336471800000f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a00000000000000000000000000000000000000000000000000bf117f1ff35aaa2f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b8400000000000000000000000000000000000000000000000000bf117f1ff35aaa2000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afb8a00000000000000000000000000000000000000000000000603e869f9450289e2c00000000000000000000000000000000000000000056368c96672550bfd7864d0000000000000000000000000000000000000000005fd07e54af1384c7481440000000000000000000000000000000000000000003ccb6fd0d85b250934abfee00000000000000000000000000000000000000000477de475fd95229353c433ff87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b94172370d5cd63279efa6d502dab29171933a610aff863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000003df8f92b7e798820ddcca2ebea7babda2c90c4ada0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f8bc943df8f92b7e798820ddcca2ebea7babda2c90c4adf863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b840000000000000000000000000000000000000000000000204d12df5dc51c6da77000000000000000000000000000000000000000003ccb6fd0d85b250934abfeef8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a0000000000000000000000000172370d5cd63279efa6d502dab29171933a610afa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383a000000000000000000000000000000000000000000000000000ce772a4f4e4308f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f842a04c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4fa0000000000000000000000000e8599f3cc5d38a9ad6f3684cd5cea72f10dbc383b84000000000000000000000000000000000000000000000000000ce772a4f4e4308000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f8fb948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff842a0804c9b842b2748a22bb64b345453a3de7ca54a6ca45ce00d415894979e22897aa00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3b8a000000000000000000000000000000000000000000008787373c577c1c258b0a80000000000000000000000000000000000000000003496b1bb9e79a4f34620b50000000000000000000000000000000000000000005df29b2a02800e654620b5000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd5070000000000000000000000000000000000000000050c2b7e22f9c35395d37b02f87b948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff863a044c58d81365b66dd4b1a7f36c25aa97b8c71c361ee4937adc1a00000227db5dda00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f77280f89b949a71012b13ca4d3d0cdc72a177df3ef03b0e76a3f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c4195d4060daeac44058ed668aa5efec50d77ff6a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b94c4195d4060daeac44058ed668aa5efec50d77ff6f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f8bc94c4195d4060daeac44058ed668aa5efec50d77ff6f863a05d624aa9c148153ab3446c1b154f660ee7701e549fe9b62dab7171b1c80e6fa2a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1b84000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8000000000000000000000000000000000000000003f3bf3d1f1ef75fa79fd507f8bc948dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcff884a03115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7a00000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a3a0000000000000000000000000dc9a35b16db4e126cfedc41322b3a36454b1f772a0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f89b948f3cf7ad23cd3cadbd9735aff958023239c6a063f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000013da329b6336471800000f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb8400000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063000000000000000000000000000000000000000000013da329b6336471800000f89b94172370d5cd63279efa6d502dab29171933a610aff863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000204d12df5dc51c6da77f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb840000000000000000000000000172370d5cd63279efa6d502dab29171933a610af000000000000000000000000000000000000000000000204d12df5dc51c6da77f89b949a71012b13ca4d3d0cdc72a177df3ef03b0e76a3f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000c928002904ec475663a83063d492ea2ae09ebda1a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f87994c928002904ec475663a83063d492ea2ae09ebda1e1a022e3f162fca16dc0fcfb65eddf406531a0c555a2c24c58cf5d10fc2d202a882eb8400000000000000000000000009a71012b13ca4d3d0cdc72a177df3ef03b0e76a300000000000000000000000000000000000000000000006572fa5fbb2fb73ec8f8fb94dc9a35b16db4e126cfedc41322b3a36454b1f772f842a0f5efc4bb09a12b6c9561a7e7ab02938a72a4351316b473d574fdaaa89c43eb9aa0000000000000000000000000da98b308be8766501ec7fe3ed9a48efbd6c31a7bb8a000000000000000000000000000000000000000000000000000000000000000470000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f87b94da98b308be8766501ec7fe3ed9a48efbd6c31a7bf863a01d356dc5da7bf4f74d415f1adff04022530e2418a8e8458e4fa0dca4cec14250a00000000000000000000000000000000000000000000000000000000000000047a0000000000000000000000000000000000000000000000000000000000000000080f9015d9402777053d6764996e594c3e88af1d58d5363a2e6f884a0caacad83e47cc45c280d487ec84184eee2fa3b54ebaa393bda7549f13da228f6a00ba6f5a29753ee4861917fbae7122075257c5a8b702791ecdca09fd4abfb40e5a00000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000d9a31dc8347284a6bea9598d49d8dacbfd5774f1b8c00000000000000000000000000000000000000000000000000036fe68904af8cc00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000047f9013d940000000000000000000000000000000000001010f884a04dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63a00000000000000000000000000000000000000000000000000000000000001010a0000000000000000000000000d9a31dc8347284a6bea9598d49d8dacbfd5774f1a0000000000000000000000000bdbd4347b082d9d6bdf2da4555a37ce52a2e2120b8a000000000000000000000000000000000000000000000000001140015237d04970000000000000000000000000000000000000000000000234e3393093dd75603000000000000000000000000000000000000000000004578091978720a7a78fe0000000000000000000000000000000000000000000000234d1f92f41a5a516c0000000000000000000000000000000000000000000045780a2d78872df77d9582002624'; + + uint256 balanceDaiBefore = IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf( + MiscEthereum.AAVE_POL_ETH_BRIDGE + ); + + IAavePolEthERC20Bridge(MiscEthereum.AAVE_POL_ETH_BRIDGE).exit(burnProof); + + assertGt( + IERC20(AaveV3EthereumAssets.DAI_UNDERLYING).balanceOf(MiscEthereum.AAVE_POL_ETH_BRIDGE), + balanceDaiBefore + ); + } +} From b15b6a32b2aa3cd948a33de2e1dfd7079bb04404 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Wed, 8 Nov 2023 15:05:43 -0500 Subject: [PATCH 04/15] chore: add missing natspec --- src/bridges/AavePolEthERC20Bridge.sol | 1 + src/bridges/IAavePolEthERC20Bridge.sol | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index 6f2a33825..95e7ec872 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -40,6 +40,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { address public constant ROOT_CHAIN_MANAGER = 0xA0c68C638235ee32657e8f720a23ceC1bFc77C77; + /// @param _owner The owner of the contract upon deployment constructor(address _owner) { _transferOwnership(_owner); } diff --git a/src/bridges/IAavePolEthERC20Bridge.sol b/src/bridges/IAavePolEthERC20Bridge.sol index d219c44be..b945dafcd 100644 --- a/src/bridges/IAavePolEthERC20Bridge.sol +++ b/src/bridges/IAavePolEthERC20Bridge.sol @@ -3,6 +3,11 @@ pragma solidity ^0.8.0; interface IAavePolEthERC20Bridge { + /* + * Returns the address of the Mainnet contract to exit the burn from + */ + function ROOT_CHAIN_MANAGER() external view returns (address); + /* * This function withdraws an ERC20 token from Polygon to Mainnet. exit() needs * to be called on mainnet with the corresponding burnProof in order to complete. From e389ae95287148bfc873705393719a0910223d5f Mon Sep 17 00:00:00 2001 From: efecarranza Date: Wed, 8 Nov 2023 15:48:53 -0500 Subject: [PATCH 05/15] feat: add isTokenMapped function --- src/bridges/AavePolEthERC20Bridge.sol | 9 ++++++++ src/bridges/IAavePolEthERC20Bridge.sol | 13 ++++++++++-- src/bridges/README.md | 11 ++++++++++ tests/bridges/AavePolEthERC20BridgeTest.t.sol | 21 +++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index 95e7ec872..6d0104994 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -13,6 +13,8 @@ import {ChainIds} from '../ChainIds.sol'; import {IAavePolEthERC20Bridge} from './IAavePolEthERC20Bridge.sol'; interface IRootChainManager { + function childToRootToken(address token) external view returns (address); + function exit(bytes calldata inputData) external; } @@ -82,6 +84,13 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { emit WithdrawToCollector(token, balance); } + /// @inheritdoc IAavePolEthERC20Bridge + function isTokenMapped(address l2token) external view returns (bool) { + if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); + + return IRootChainManager(ROOT_CHAIN_MANAGER).childToRootToken(l2token) != address(0); + } + /// @inheritdoc Rescuable function whoCanRescue() public view override returns (address) { return owner(); diff --git a/src/bridges/IAavePolEthERC20Bridge.sol b/src/bridges/IAavePolEthERC20Bridge.sol index b945dafcd..cf4b9ebd2 100644 --- a/src/bridges/IAavePolEthERC20Bridge.sol +++ b/src/bridges/IAavePolEthERC20Bridge.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.0; interface IAavePolEthERC20Bridge { /* - * Returns the address of the Mainnet contract to exit the burn from - */ + * Returns the address of the Mainnet contract to exit the burn from + */ function ROOT_CHAIN_MANAGER() external view returns (address); /* @@ -39,4 +39,13 @@ interface IAavePolEthERC20Bridge { * @param token Mainnet address of token to withdraw to Collector */ function withdrawToCollector(address token) external; + + /* + * This function checks whether the L2 token to L1 token mapping exists. + * If the mapping doesn't exist, DO NOT BRIDGE from Polygon. + * @notice Call on Mainnet only. + * @param l2token Address of the token on Polygon. + * @returns Boolean denoting whether mapping exists or not. + */ + function isTokenMapped(address l2token) external view returns (bool); } diff --git a/src/bridges/README.md b/src/bridges/README.md index 4142e2f06..0c2f423a5 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -14,6 +14,11 @@ Callable on Polygon to withdraw ERC20 token. It withdraws `amount` of passed `to Callable on Mainnet to finish the withdrawal process. Callable 30-90 minutes after `bridge()` is called and proof is available via API. +`function exit(bytes[] calldata burnProofs) external;` + +Callable on Mainnet to finish the withdrawal process. Callable 30-90 minutes after `bridge()` is called and proof is available via API. +This function takes an array of proofs to do multiple burns in one transaction. + `function withdrawToCollector(address token) external;` Callable on Mainnet. Withdraws balance of held token to the Aave Collector. @@ -22,6 +27,12 @@ Callable on Mainnet. Withdraws balance of held token to the Aave Collector. Callable on Polygon. Withdraws tokens from bridge contract back to Aave Collector on Polygon. +`function isTokenMapped(address l2token) external view returns(bool);` + +Callable on Mainnet. Returns whether a token mapping exists between Polygon and Mainnet. + +**DO NOT BRIDGE** if this function returns false, funds will be lost forever. + ## Burn Proof Generation After you have called `bridge()` Polygon, it will take 30-90 minutes for a checkpoint to happen. Once the next checkpoint includes the burn transaction, you can withdraw the tokens on Mainnet. diff --git a/tests/bridges/AavePolEthERC20BridgeTest.t.sol b/tests/bridges/AavePolEthERC20BridgeTest.t.sol index 5290cb3a6..a2685b979 100644 --- a/tests/bridges/AavePolEthERC20BridgeTest.t.sol +++ b/tests/bridges/AavePolEthERC20BridgeTest.t.sol @@ -164,6 +164,27 @@ contract WithdrawToCollectorTest is AavePolEthERC20BridgeTest { } } +contract IsTokenMapped is AavePolEthERC20BridgeTest { + function test_revertsIf_invalidChain() public { + vm.selectFork(polygonFork); + + vm.expectRevert(AavePolEthERC20Bridge.InvalidChain.selector); + bridgeMainnet.isTokenMapped(AaveV3PolygonAssets.USDC_UNDERLYING); + } + + function test_successful_returnsTrue() public { + vm.selectFork(mainnetFork); + + assertTrue(bridgeMainnet.isTokenMapped(AaveV3PolygonAssets.USDC_UNDERLYING)); + } + + function test_successful_returnsFalse() public { + vm.selectFork(mainnetFork); + + assertFalse(bridgeMainnet.isTokenMapped(makeAddr('new-erc20-token'))); + } +} + /* * No good way of testing the full flow as proof is generated via API 30-90 minutes after the * bridge() function is called on Polygon. From 8eeea7618be44010314f951c72e82f64bdd09417 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Wed, 8 Nov 2023 20:18:01 -0500 Subject: [PATCH 06/15] Update README.md --- src/bridges/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 0c2f423a5..db78c74ca 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -23,7 +23,7 @@ This function takes an array of proofs to do multiple burns in one transaction. Callable on Mainnet. Withdraws balance of held token to the Aave Collector. -`function rescueTokens(address[] calldata tokens) external;` +`function emergencyTokenTransfer(address erc20Token, address to, uint256 amount) external;` Callable on Polygon. Withdraws tokens from bridge contract back to Aave Collector on Polygon. From 7579fbb8378d9e82d4f41d64d094e4c76ca8d9ad Mon Sep 17 00:00:00 2001 From: efecarranza Date: Wed, 15 Nov 2023 15:47:10 -0500 Subject: [PATCH 07/15] feat: check against 0xeee --- src/bridges/AavePolEthERC20Bridge.sol | 8 ++++- tests/bridges/AavePolEthERC20BridgeTest.t.sol | 30 +++++++++++-------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index 6d0104994..dfb955d9b 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -88,7 +88,13 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { function isTokenMapped(address l2token) external view returns (bool) { if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); - return IRootChainManager(ROOT_CHAIN_MANAGER).childToRootToken(l2token) != address(0); + address token = IRootChainManager(ROOT_CHAIN_MANAGER).childToRootToken(l2token); + + if (token == address(0) || token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { + return false; + } + + return true; } /// @inheritdoc Rescuable diff --git a/tests/bridges/AavePolEthERC20BridgeTest.t.sol b/tests/bridges/AavePolEthERC20BridgeTest.t.sol index a2685b979..9e8d9ef34 100644 --- a/tests/bridges/AavePolEthERC20BridgeTest.t.sol +++ b/tests/bridges/AavePolEthERC20BridgeTest.t.sol @@ -26,16 +26,16 @@ contract AavePolEthERC20BridgeTest is Test { uint256 mainnetFork; uint256 polygonFork; - address USDC_WHALE = 0xF977814e90dA44bFA03b6295A0616a897441aceC; + address USDC_WHALE = 0xf89d7b9c864f589bbF53a82105107622B35EaA40; address USDC_WHALE_MAINNET = 0xcEe284F754E854890e311e3280b767F80797180d; function setUp() public { bytes32 salt = keccak256(abi.encode(tx.origin, uint256(0))); - mainnetFork = vm.createSelectFork(vm.rpcUrl('mainnet'), 17921144); + mainnetFork = vm.createSelectFork(vm.rpcUrl('mainnet'), 18579720); bridgeMainnet = new AavePolEthERC20Bridge{salt: salt}(address(this)); - polygonFork = vm.createSelectFork(vm.rpcUrl('polygon'), 46340897); + polygonFork = vm.createSelectFork(vm.rpcUrl('polygon'), 49986900); bridgePolygon = new AavePolEthERC20Bridge{salt: salt}(address(this)); } } @@ -95,36 +95,36 @@ contract EmergencyTokenTransfer is AavePolEthERC20BridgeTest { } function test_successful_governanceCaller() public { - address BAL_WHALE = 0x7Ba7f4773fa7890BaD57879F0a1Faa0eDffB3520; + address LINK_WHALE = 0x61167073E31b1DAd85a3E531211c7B8F1E5cAE72; - assertEq(IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(bridgePolygon)), 0); + assertEq(IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).balanceOf(address(bridgePolygon)), 0); uint256 balAmount = 1_000e18; - vm.startPrank(BAL_WHALE); - IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).transfer(address(bridgePolygon), balAmount); + vm.startPrank(LINK_WHALE); + IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).transfer(address(bridgePolygon), balAmount); vm.stopPrank(); assertEq( - IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(bridgePolygon)), + IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).balanceOf(address(bridgePolygon)), balAmount ); - uint256 initialCollectorBalBalance = IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf( + uint256 initialCollectorBalBalance = IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).balanceOf( address(AaveV2Polygon.COLLECTOR) ); bridgePolygon.emergencyTokenTransfer( - AaveV2PolygonAssets.BAL_UNDERLYING, + AaveV2PolygonAssets.LINK_UNDERLYING, address(AaveV2Polygon.COLLECTOR), balAmount ); assertEq( - IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(AaveV2Polygon.COLLECTOR)), + IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).balanceOf(address(AaveV2Polygon.COLLECTOR)), initialCollectorBalBalance + balAmount ); - assertEq(IERC20(AaveV2PolygonAssets.BAL_UNDERLYING).balanceOf(address(bridgePolygon)), 0); + assertEq(IERC20(AaveV2PolygonAssets.LINK_UNDERLYING).balanceOf(address(bridgePolygon)), 0); } } @@ -183,6 +183,12 @@ contract IsTokenMapped is AavePolEthERC20BridgeTest { assertFalse(bridgeMainnet.isTokenMapped(makeAddr('new-erc20-token'))); } + + function test_successful_returnsFalseWeth() public { + vm.selectFork(mainnetFork); + + assertFalse(bridgeMainnet.isTokenMapped(AaveV3PolygonAssets.WETH_UNDERLYING)); + } } /* From b9684c73c886bc26f95520eea128fd771d822bf9 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Thu, 16 Nov 2023 13:12:46 -0500 Subject: [PATCH 08/15] chore: add TXs to README --- src/bridges/README.md | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 0c2f423a5..13d2343ea 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -6,6 +6,37 @@ The same contract exists on both chains with the same address, so this contract ## Functions +`function isTokenMapped(address l2token) external view returns(bool);` + +Callable on Mainnet. Returns whether a token mapping exists between Polygon and Mainnet. + +**DO NOT BRIDGE** if this function returns false, funds will be lost forever. + +Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped or not, and respective transactions showing a bridge. + +| Token | Is Mapped | Burn | Exit | +| ------- | --------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | +| DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | +| LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | +| WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | +| CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | +| BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | +| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | | +| WETH | NO | NO | NO | +| WMATIC | NO | NO | NO | +| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | | +| GHST | yes | | | +| DPI | yes | | | +| SUSHI | yes | | | +| EURS | yes | | | +| jEUR | NO | NO | NO | +| agEUR | yes | | | +| miMATIC | NO | NO | NO | +| stMATIC | yes | | | +| MaticX | yes | | | +| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | | + `function bridge(address token, uint256 amount) external;` Callable on Polygon to withdraw ERC20 token. It withdraws `amount` of passed `token` to mainnet. @@ -27,12 +58,6 @@ Callable on Mainnet. Withdraws balance of held token to the Aave Collector. Callable on Polygon. Withdraws tokens from bridge contract back to Aave Collector on Polygon. -`function isTokenMapped(address l2token) external view returns(bool);` - -Callable on Mainnet. Returns whether a token mapping exists between Polygon and Mainnet. - -**DO NOT BRIDGE** if this function returns false, funds will be lost forever. - ## Burn Proof Generation After you have called `bridge()` Polygon, it will take 30-90 minutes for a checkpoint to happen. Once the next checkpoint includes the burn transaction, you can withdraw the tokens on Mainnet. @@ -58,5 +83,5 @@ If doing multiple burns in one transaction, each has to be processed individuall ## Deployed Addresses -Mainnet: -Polygon: +Mainnet: [0xf1b293C69E9DD2057e5F1279799b828A83867E41](https://etherscan.io/address/0xf1b293C69E9DD2057e5F1279799b828A83867E41) +Polygon: [0xf1b293C69E9DD2057e5F1279799b828A83867E41](https://polygonscan.com/address/0xf1b293C69E9DD2057e5F1279799b828A83867E41) From eb99fbffbe8427b32df3dfe1aa47a2c795af75a7 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Thu, 16 Nov 2023 16:55:24 -0500 Subject: [PATCH 09/15] chore: add tx to exit --- src/bridges/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 281233c79..8caeda5a7 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -22,10 +22,10 @@ Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped | WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | | CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | | BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | -| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | | +| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | | WETH | NO | NO | NO | | WMATIC | NO | NO | NO | -| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | | +| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | | GHST | yes | | | | DPI | yes | | | | SUSHI | yes | | | @@ -35,7 +35,7 @@ Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped | miMATIC | NO | NO | NO | | stMATIC | yes | | | | MaticX | yes | | | -| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | | +| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | `function bridge(address token, uint256 amount) external;` From d8639ef7e8decd589c59769ba7f123e6beb07e31 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Sun, 19 Nov 2023 18:48:56 -0500 Subject: [PATCH 10/15] feat: forward eth --- src/bridges/AavePolEthERC20Bridge.sol | 18 ++++++++++------- src/bridges/README.md | 14 ++++++++----- tests/bridges/AavePolEthERC20BridgeTest.t.sol | 20 +++++++++++++++++-- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/bridges/AavePolEthERC20Bridge.sol b/src/bridges/AavePolEthERC20Bridge.sol index dfb955d9b..bb9acab29 100644 --- a/src/bridges/AavePolEthERC20Bridge.sol +++ b/src/bridges/AavePolEthERC20Bridge.sol @@ -37,6 +37,7 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { error InvalidChain(); event Exit(bytes proof); + event FailedToSendETH(); event Bridge(address token, uint256 amount); event WithdrawToCollector(address token, uint256 amount); @@ -88,17 +89,20 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge { function isTokenMapped(address l2token) external view returns (bool) { if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); - address token = IRootChainManager(ROOT_CHAIN_MANAGER).childToRootToken(l2token); - - if (token == address(0) || token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { - return false; - } - - return true; + return IRootChainManager(ROOT_CHAIN_MANAGER).childToRootToken(l2token) != address(0); } /// @inheritdoc Rescuable function whoCanRescue() public view override returns (address) { return owner(); } + + receive() external payable { + if (block.chainid != ChainIds.MAINNET) revert InvalidChain(); + + (bool success, ) = address(AaveV3Ethereum.COLLECTOR).call{value: address(this).balance}(""); + if (!success) { + emit FailedToSendETH(); + } + } } diff --git a/src/bridges/README.md b/src/bridges/README.md index 8caeda5a7..92ce61b5d 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -15,15 +15,15 @@ Callable on Mainnet. Returns whether a token mapping exists between Polygon and Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped or not, and respective transactions showing a bridge. | Token | Is Mapped | Burn | Exit | -| ------- | --------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| ------- | --------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | | USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | | DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | | LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | | WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | | CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | | BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | -| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | -| WETH | NO | NO | NO | +| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | +| WETH | yes | | [Tx](https://etherscan.io/tx/0xcc48570ce89313e09a7b62867332f7f7415168500486aa4974c9748146dd7713) | | WMATIC | NO | NO | NO | | AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | | GHST | yes | | | @@ -58,6 +58,10 @@ Callable on Mainnet. Withdraws balance of held token to the Aave Collector. Callable on Polygon. Withdraws tokens from bridge contract back to Aave Collector on Polygon. +`receive() external payable;` + +Function to receive Ether and forward it to Aave Collector. If not mainnet, it will revert. + ## Burn Proof Generation After you have called `bridge()` Polygon, it will take 30-90 minutes for a checkpoint to happen. Once the next checkpoint includes the burn transaction, you can withdraw the tokens on Mainnet. @@ -83,5 +87,5 @@ If doing multiple burns in one transaction, each has to be processed individuall ## Deployed Addresses -Mainnet: [0xf1b293C69E9DD2057e5F1279799b828A83867E41](https://etherscan.io/address/0xf1b293C69E9DD2057e5F1279799b828A83867E41) -Polygon: [0xf1b293C69E9DD2057e5F1279799b828A83867E41](https://polygonscan.com/address/0xf1b293C69E9DD2057e5F1279799b828A83867E41) +Mainnet: [0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36](https://etherscan.io/address/0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36) +Polygon: [0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36](https://polygonscan.com/address/0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36) diff --git a/tests/bridges/AavePolEthERC20BridgeTest.t.sol b/tests/bridges/AavePolEthERC20BridgeTest.t.sol index 9e8d9ef34..005867fbc 100644 --- a/tests/bridges/AavePolEthERC20BridgeTest.t.sol +++ b/tests/bridges/AavePolEthERC20BridgeTest.t.sol @@ -183,11 +183,27 @@ contract IsTokenMapped is AavePolEthERC20BridgeTest { assertFalse(bridgeMainnet.isTokenMapped(makeAddr('new-erc20-token'))); } +} + +contract ReceiveEther is AavePolEthERC20BridgeTest { + function test_revertsIf_invalidChain() public { + vm.selectFork(polygonFork); + + vm.expectRevert(AavePolEthERC20Bridge.InvalidChain.selector); + address(bridgePolygon).call{value: 1 ether}(""); + } - function test_successful_returnsFalseWeth() public { + function test_successful_forwardsETH() public { vm.selectFork(mainnetFork); - assertFalse(bridgeMainnet.isTokenMapped(AaveV3PolygonAssets.WETH_UNDERLYING)); + uint256 balanceETHBefore = address(AaveV3Ethereum.COLLECTOR).balance; + + assertEq(address(bridgeMainnet).balance, 0); + + address(bridgeMainnet).call{value: 1 ether}(""); + + assertEq(balanceETHBefore + 1 ether, address(AaveV3Ethereum.COLLECTOR).balance); + assertEq(address(bridgeMainnet).balance, 0); } } From e505df6cb5ab7ab81b4d736f87f3569992db11d5 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Mon, 20 Nov 2023 15:33:57 -0500 Subject: [PATCH 11/15] chore: cleanup readme --- src/bridges/README.md | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 92ce61b5d..d4fe1f333 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -14,28 +14,28 @@ Callable on Mainnet. Returns whether a token mapping exists between Polygon and Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped or not, and respective transactions showing a bridge. -| Token | Is Mapped | Burn | Exit | -| ------- | --------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | -| USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | -| DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | -| LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | -| WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | -| CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | -| BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | -| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | -| WETH | yes | | [Tx](https://etherscan.io/tx/0xcc48570ce89313e09a7b62867332f7f7415168500486aa4974c9748146dd7713) | -| WMATIC | NO | NO | NO | -| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | -| GHST | yes | | | -| DPI | yes | | | -| SUSHI | yes | | | -| EURS | yes | | | -| jEUR | NO | NO | NO | -| agEUR | yes | | | -| miMATIC | NO | NO | NO | -| stMATIC | yes | | | -| MaticX | yes | | | -| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | +| Token | Is Mapped | Burn | Exit | +| --- | --- | --- | --- | --- | +| USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | +| DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | +| LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | +| WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | +| CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | +| BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | +| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | +| WETH | yes | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | [Tx](https://etherscan.io/tx/0xcc48570ce89313e09a7b62867332f7f7415168500486aa4974c9748146dd7713) | +| WMATIC | NO | NO | NO | +| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | +| GHST | yes | | | +| DPI | yes | | | +| SUSHI | yes | | | +| EURS | yes | | | +| jEUR | NO | NO | NO | +| agEUR | yes | | | +| miMATIC | NO | NO | NO | +| stMATIC | yes | | | +| MaticX | yes | | | +| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | `function bridge(address token, uint256 amount) external;` From 763ff8ffeef3e75ea45ad4eb9d28cf63473d9b77 Mon Sep 17 00:00:00 2001 From: efecarranza Date: Mon, 20 Nov 2023 15:39:45 -0500 Subject: [PATCH 12/15] chore: remove column --- src/bridges/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index d4fe1f333..f3a120819 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -14,8 +14,8 @@ Callable on Mainnet. Returns whether a token mapping exists between Polygon and Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped or not, and respective transactions showing a bridge. -| Token | Is Mapped | Burn | Exit | -| --- | --- | --- | --- | --- | +| Token | Is Mapped | Burn | Exit | +| --- | --- | --- | --- | | USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | | DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | | LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | From 74c80d575c07bc49335ef3df35f9869c894fca46 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Mon, 20 Nov 2023 18:45:59 -0500 Subject: [PATCH 13/15] Update README.md --- src/bridges/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index f3a120819..500ce21bf 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -16,16 +16,16 @@ Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped | Token | Is Mapped | Burn | Exit | | --- | --- | --- | --- | -| USDC | yes | [Tx](https://polygonscan.com/tx/0x954e823985e203318308073b0692e360ca9842ea0d29ed578eafc14b801621dc) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | -| DAI | yes | [Tx](https://polygonscan.com/tx/0x1c455d8f60f73a757ef5752a8cd3ed04b00ba25026dc7d596b4ee7d8b4a099c2) | [Tx](https://etherscan.io/tx/0x7c54d6b96a7474300d64e2fdae042947aaa92dcc0a7af061f02f335839fdcb56) | -| LINK | yes | [Tx](https://polygonscan.com/tx/0x4d5e59f05884fc4f56afcd04bc8705ae7ed12eed4eaef7852a673075011fb10b) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | -| WBTC | yes | [Tx](https://polygonscan.com/tx/0x6fbabbf54aec01502db6739ce1616870ce3e3b6c0626b140c0b75a8c16fdfb19) | [Tx](https://etherscan.io/tx/0x342938e2a9d4f846cde15258c7aeffade7a42b729d97ee310308eeb912a734e8) | -| CRV | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x70e4880529959951052a7f73bd91890c793ca4ba03a3b9571b75896968d3ef42) | -| BAL | yes | [Tx](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567) | [Tx](https://etherscan.io/tx/0x7cd55a0cf1f6dfb16dc7913271ae3f0cd8af78ad90c3c23a82112683e16ac574) | -| USDT | yes | [Tx](https://polygonscan.com/tx/0x67d7954f28d446a64aa3d4276d3329d3fc33ced155c9d82403a4d59ae248c0a7) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | -| WETH | yes | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | [Tx](https://etherscan.io/tx/0xcc48570ce89313e09a7b62867332f7f7415168500486aa4974c9748146dd7713) | +| USDC | yes | [Tx](https://polygonscan.com/tx/0xd670439927d5b067b742e79a2c2f8ac375f38ac0fe77b77bfcdd5a4d7b60f8b7) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| DAI | yes | [Tx](https://polygonscan.com/tx/0x3827bda3f18f117b1b216b2152465708a6e72dfb8bbb2f91c0dcf7a19f817fcc) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| LINK | yes | [Tx](https://polygonscan.com/tx/0x5cbe8749bb496627ab6f53c3ef7f8b451c2f9a3e7933c0231f09d70696615e20) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| WBTC | yes | [Tx](https://polygonscan.com/tx/0xd95ba8488fb67146b7a5946977db3c74433928c0cf1ef08802e46b40cd8a53d6) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| CRV | yes | [Tx](https://polygonscan.com/tx/0x144f5532d1bf88bbdbd914c9d79caaf7e3861aefb0412db69fd46136a4232246) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| BAL | yes | [Tx](https://polygonscan.com/tx/0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| USDT | yes | [Tx](https://polygonscan.com/tx/0xfd091ad2753435126d09c88168234a0c8d536ebc1c942359f02081f8a9d595a2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| WETH | yes | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | WMATIC | NO | NO | NO | -| AAVE | yes | [Tx](https://polygonscan.com/tx/0xba939d05ab27aedd931b015af970d9b8a73fa903e705be3e3c707ef3b8c91fb2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | +| AAVE | yes | [Tx](https://polygonscan.com/tx/0x338f0b763cd4f4080cb0f54a8b76172cd750a21d3f2960ef6e19960a0e9c7df2) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | GHST | yes | | | | DPI | yes | | | | SUSHI | yes | | | @@ -35,7 +35,7 @@ Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped | miMATIC | NO | NO | NO | | stMATIC | yes | | | | MaticX | yes | | | -| wstETH | yes | [Tx](https://polygonscan.com/tx/0x1237237d8d9ef85fd395867121f22895102a92bde06d3ad3363026809a472fd2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | +| wstETH | yes | [Tx](https://polygonscan.com/tx/0x30a6f403211fea0edcd2fcd89e505eb0bd6b584a375482e80beec21537a20291) | [Tx](https://etherscan.io/tx/0xa521582be2bb589055827d1556acc4255dad981286ec01942a991b0d31edceaa) | `function bridge(address token, uint256 amount) external;` From 6280c37204ddcd97c8a1b0b50cc4243e7fd32246 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Tue, 21 Nov 2023 09:01:03 -0500 Subject: [PATCH 14/15] Update README.md --- src/bridges/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 500ce21bf..9f002996e 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -22,7 +22,7 @@ Here's a list of Polygon Aave V2 and Aave V3 tokens and whether they are mapped | WBTC | yes | [Tx](https://polygonscan.com/tx/0xd95ba8488fb67146b7a5946977db3c74433928c0cf1ef08802e46b40cd8a53d6) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | CRV | yes | [Tx](https://polygonscan.com/tx/0x144f5532d1bf88bbdbd914c9d79caaf7e3861aefb0412db69fd46136a4232246) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | BAL | yes | [Tx](https://polygonscan.com/tx/0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | -| USDT | yes | [Tx](https://polygonscan.com/tx/0xfd091ad2753435126d09c88168234a0c8d536ebc1c942359f02081f8a9d595a2) | [Tx](https://etherscan.io/tx/0x693c1d2055319bc969291ef29b5ca1dfdae37193d71170ce700dac9b44e0ef33) | [Tx](https://polygonscan.com/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | +| USDT | yes | [Tx](https://polygonscan.com/tx/0xfd091ad2753435126d09c88168234a0c8d536ebc1c942359f02081f8a9d595a2) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | [Tx](https://polygonscan.com/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | WETH | yes | [Tx](https://polygonscan.com/tx/0x813c4821f5da822a0f60db31070ca025f57ff81953f42f95270a77bc941b266d) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | | WMATIC | NO | NO | NO | | AAVE | yes | [Tx](https://polygonscan.com/tx/0x338f0b763cd4f4080cb0f54a8b76172cd750a21d3f2960ef6e19960a0e9c7df2) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) | From b7cc7cec9dda643bbbae086248eaf1b04be255c9 Mon Sep 17 00:00:00 2001 From: Fermin 'Piscu' Carranza Date: Tue, 21 Nov 2023 09:26:11 -0500 Subject: [PATCH 15/15] Update README.md --- src/bridges/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bridges/README.md b/src/bridges/README.md index 9f002996e..ac577a91e 100644 --- a/src/bridges/README.md +++ b/src/bridges/README.md @@ -70,20 +70,21 @@ The API endpoint used to generate the burn proof is as follows, where `TRANSACTI https://proof-generator.polygon.technology/api/v1/matic/exit-payload/?eventSignature= -Here's a sample transaction: https://polygonscan.com/tx/0x08365e09c94c5796ae300e706cc516714661a42c50dfff2fa1e9a01b036b21d6 +Here's a sample transaction: https://polygonscan.com/tx/0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb The log topic to use is the `Transfer` function to the zero address (aka. burn). -https://polygonscan.com/tx/0x08365e09c94c5796ae300e706cc516714661a42c50dfff2fa1e9a01b036b21d6#eventlog +https://polygonscan.com/tx/0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb#eventlog -TRANSACTION_HASH: 0x08365e09c94c5796ae300e706cc516714661a42c50dfff2fa1e9a01b036b21d6 +TRANSACTION_HASH: 0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb EVENT_SIGNATURE: 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef -And the generated proof: https://proof-generator.polygon.technology/api/v1/matic/exit-payload/0x08365e09c94c5796ae300e706cc516714661a42c50dfff2fa1e9a01b036b21d6?eventSignature=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef +And the generated proof: https://proof-generator.polygon.technology/api/v1/matic/exit-payload/0xafa75edc210566b4d9e3b0986c433f77531eae8a3fb51d4b4e27bf0b241782bb?eventSignature=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef The result is the bytes data that is later passed to `exit()`. -If doing multiple burns in one transaction, each has to be processed individually via exit. To get a specific logIndex to generate the correct proof when doing multiple, you can append to the API URL `&tokenIndex=[INDEX_OF_TARGET_LOG]`. +If doing multiple burns in one transaction, each proof has to be generated individually. To get a specific logIndex to generate the correct proof when doing multiple, you can append to the API URL `&tokenIndex=[INDEX_OF_TARGET_LOG]`. The Index of the target log is the # of the `Transfer()` function, with a 0 based index. A sample transaction with multiple burns can be seen [here.](https://polygonscan.com/tx/0xc73b85175045e272161abe38b25eac76546eea20247d0947926d7ef4e901b567#eventlog) +An array of proofs can be passed to the `exit(bytes[] memory proofs)` function to do all withdrawals in a single transaction instead of the regular `exit(bytes memory proof)` method, on the Mainnet contract. ## Deployed Addresses