Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PolEthBridge: Update bridge owner and README as well as add missing natspec #166

Merged
merged 16 commits into from
Nov 21, 2023
Merged
7 changes: 4 additions & 3 deletions scripts/DeployBridges.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
57 changes: 37 additions & 20 deletions src/bridges/AavePolEthERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -34,48 +36,46 @@ contract AavePolEthERC20Bridge is Ownable, Rescuable, IAavePolEthERC20Bridge {

error InvalidChain();

event Exit();
event Exit(bytes proof);
event FailedToSendETH();
event Bridge(address token, uint256 amount);
event WithdrawToCollector(address token, uint256 amount);

address public constant ROOT_CHAIN_MANAGER = 0xA0c68C638235ee32657e8f720a23ceC1bFc77C77;

/// @param _owner The owner of the contract upon deployment
constructor(address _owner) {
_transferOwnership(_owner);
sendra marked this conversation as resolved.
Show resolved Hide resolved
}

/*
* 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();

IERC20Polygon(token).withdraw(amount);
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();

IRootChainManager(ROOT_CHAIN_MANAGER).exit(burnProof);
emit Exit();
emit Exit(burnProof);
}

/*
* 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 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
function withdrawToCollector(address token) external {
if (block.chainid != ChainIds.MAINNET) revert InvalidChain();

Expand All @@ -85,7 +85,24 @@ 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();
}

receive() external payable {
if (block.chainid != ChainIds.MAINNET) revert InvalidChain();

(bool success, ) = address(AaveV3Ethereum.COLLECTOR).call{value: address(this).balance}("");
if (!success) {
emit FailedToSendETH();
}
}
}
40 changes: 40 additions & 0 deletions src/bridges/IAavePolEthERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,49 @@
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.
* @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;

/*
* 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.
* @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);
}
48 changes: 45 additions & 3 deletions src/bridges/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/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/0x338f0b763cd4f4080cb0f54a8b76172cd750a21d3f2960ef6e19960a0e9c7df2) | [Tx](https://etherscan.io/tx/0x5b410b2d35acefe23785fca64242521503720c89540cba7580a96c7d48de65ff) |
| 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/0x30a6f403211fea0edcd2fcd89e505eb0bd6b584a375482e80beec21537a20291) | [Tx](https://etherscan.io/tx/0xa521582be2bb589055827d1556acc4255dad981286ec01942a991b0d31edceaa) |

`function bridge(address token, uint256 amount) external;`

Callable on Polygon to withdraw ERC20 token. It withdraws `amount` of passed `token` to mainnet.
Expand All @@ -14,14 +45,23 @@ 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.

`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.

`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.
Expand All @@ -43,7 +83,9 @@ 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:
Polygon:
Mainnet: [0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36](https://etherscan.io/address/0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36)
Polygon: [0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36](https://polygonscan.com/address/0x1C2BA5b8ab8e795fF44387ba6d251fa65AD20b36)
Loading