-
Notifications
You must be signed in to change notification settings - Fork 97
feat(bridge-withdrawer): PoC astria-bridge-withdrawer implementation #984
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
Changes from all commits
3d98bc4
312ac95
dc13bb6
b36a152
badadd1
743f57d
687f371
fade698
6b3e883
9e860e2
4d8a8ad
75a1b29
16ebcf6
397ddbb
c41a562
014c51f
3ccc909
ee8ceec
631b090
4e78e99
455d532
b78dfd8
c61bd2e
fc0237d
80336fa
7b71c86
d22c387
1879617
1b3c1f7
0e115f7
10ad97a
4ee6fd1
6ce8d8e
f914103
bee7fb3
4a914f8
2dfd7c4
7271f75
7aba534
9029d02
6968898
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [submodule "crates/astria-bridge-withdrawer/ethereum/lib/forge-std"] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we have the contracts outside of crates in the monorepo perhaps? |
||
| path = crates/astria-bridge-withdrawer/ethereum/lib/forge-std | ||
| url = https://github.com/foundry-rs/forge-std | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| [package] | ||
| name = "astria-bridge-withdrawer" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| rust-version = "1.73" | ||
| license = "MIT OR Apache-2.0" | ||
| readme = "README.md" | ||
| repository = "https://github.com/astriaorg/astria" | ||
| homepage = "https://astria.org" | ||
|
|
||
| [[bin]] | ||
| name = "astria-bridge-withdrawer" | ||
|
|
||
| [dependencies] | ||
| http = "0.2.9" | ||
|
|
||
| axum = { workspace = true } | ||
| futures = { workspace = true } | ||
| hex = { workspace = true } | ||
| ethers = { workspace = true, features = ["ethers-solc", "ws"] } | ||
| hyper = { workspace = true } | ||
| humantime = { workspace = true } | ||
| ibc-types = { workspace = true } | ||
| metrics = { workspace = true } | ||
| pin-project-lite = { workspace = true } | ||
| prost = { workspace = true } | ||
| serde = { workspace = true, features = ["derive"] } | ||
| serde_json = { workspace = true } | ||
| sha2 = { workspace = true } | ||
| tendermint = { workspace = true } | ||
| tracing = { workspace = true } | ||
| tryhard = { workspace = true } | ||
| tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } | ||
| tokio-util = { workspace = true } | ||
|
|
||
| astria-build-info = { path = "../astria-build-info", features = ["runtime"] } | ||
| astria-core = { path = "../astria-core", features = ["serde", "server"] } | ||
| astria-eyre = { path = "../astria-eyre" } | ||
| config = { package = "astria-config", path = "../astria-config" } | ||
| sequencer-client = { package = "astria-sequencer-client", path = "../astria-sequencer-client", features = [ | ||
| "http", | ||
| ] } | ||
| telemetry = { package = "astria-telemetry", path = "../astria-telemetry", features = [ | ||
| "display", | ||
| ] } | ||
|
|
||
| [dev-dependencies] | ||
| astria-core = { path = "../astria-core", features = ["server", "test-utils"] } | ||
| astria-grpc-mock = { path = "../astria-grpc-mock" } | ||
| config = { package = "astria-config", path = "../astria-config", features = [ | ||
| "tests", | ||
| ] } | ||
|
|
||
| [build-dependencies] | ||
| astria-build-info = { path = "../astria-build-info", features = ["build"] } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
| astria_build_info::emit("bridge-withdrawer-v")?; | ||
| Ok(()) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Compiler files | ||
| cache/ | ||
| out/ | ||
|
|
||
| # Ignores development broadcast logs | ||
| !/broadcast | ||
| /broadcast/*/31337/ | ||
| /broadcast/**/dry-run/ | ||
|
|
||
| # Docs | ||
| docs/ | ||
|
|
||
| # Dotenv file | ||
| .env |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # astria-bridge-withdrawer | ||
|
|
||
| Forge project for the bridge withdrawer contract. | ||
|
|
||
| Requirements: | ||
|
|
||
| - foundry | ||
|
|
||
| Build: | ||
|
|
||
| ```sh | ||
| forge build | ||
| ``` | ||
|
|
||
| Copy the example .env: `cp local.example.env .env` | ||
|
|
||
| Put your private key in `.env` and `source .env`. | ||
|
|
||
| Deploy `AstriaWithdrawer.sol`: | ||
|
|
||
| ```sh | ||
| forge script script/AstriaWithdrawer.s.sol:AstriaWithdrawerScript \ | ||
| --rpc-url $RPC_URL --broadcast --sig "deploy()" -vvvv | ||
| ``` | ||
|
|
||
| Call `withdrawToSequencer` in `AstriaWithdrawer.sol`: | ||
|
|
||
| ```sh | ||
| forge script script/AstriaWithdrawer.s.sol:AstriaWithdrawerScript \ | ||
| --rpc-url $RPC_URL --broadcast --sig "withdrawToSequencer()" -vvvv | ||
| ``` | ||
|
|
||
| Call `withdrawToOriginChain` in `AstriaWithdrawer.sol`: | ||
|
|
||
| ```sh | ||
| forge script script/AstriaWithdrawer.s.sol:AstriaWithdrawerScript \ | ||
| --rpc-url $RPC_URL --broadcast --sig "withdrawToOriginChain()" -vvvv | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| [profile.default] | ||
| src = "src" | ||
| out = "out" | ||
| libs = ["lib"] | ||
|
|
||
| # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this file used?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is used to deploy the ethereum contract and make calls to it - see the readme in this crate |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # private key to submit txs with | ||
| PRIVATE_KEY=0x | ||
|
|
||
| # default local rpc url | ||
| RPC_URL="http://localhost:8545" | ||
|
|
||
| # divide withdrawn values by 10^ASSET_WITHDRAWAL_DECIMALS | ||
| ASSET_WITHDRAWAL_DECIMALS=12 | ||
|
|
||
| # contract address | ||
| ASTRIA_WITHDRAWER=0x5FbDB2315678afecb367f032d93F642f64180aa3 | ||
|
|
||
| # destination chain address to withdraw to on the sequencer | ||
| SEQUENCER_DESTINATION_CHAIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 | ||
|
|
||
| # destination chain address to withdraw to on the origin chain | ||
| ORIGIN_DESTINATION_CHAIN_ADDRESS="astring" | ||
|
|
||
| # amount to withdraw | ||
| AMOUNT=1000000000 |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // SPDX-License-Identifier: UNLICENSED | ||
| pragma solidity ^0.8.13; | ||
|
|
||
| import {Script, console} from "forge-std/Script.sol"; | ||
| import {AstriaWithdrawer} from "../src/AstriaWithdrawer.sol"; | ||
|
|
||
| contract AstriaWithdrawerScript is Script { | ||
| function setUp() public {} | ||
|
|
||
| function deploy() public { | ||
| uint32 assetWithdrawalDecimals = uint32(vm.envUint("ASSET_WITHDRAWAL_DECIMALS")); | ||
| uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); | ||
| vm.startBroadcast(deployerPrivateKey); | ||
| AstriaWithdrawer astriaWithdrawer = new AstriaWithdrawer(assetWithdrawalDecimals); | ||
| console.logAddress(address(astriaWithdrawer)); | ||
| vm.stopBroadcast(); | ||
| } | ||
|
|
||
| function withdrawToSequencer() public { | ||
| uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); | ||
| vm.startBroadcast(deployerPrivateKey); | ||
|
|
||
| address contractAddress = vm.envAddress("ASTRIA_WITHDRAWER"); | ||
| AstriaWithdrawer astriaWithdrawer = AstriaWithdrawer(contractAddress); | ||
|
|
||
| address destinationChainAddress = vm.envAddress("SEQUENCER_DESTINATION_CHAIN_ADDRESS"); | ||
| uint256 amount = vm.envUint("AMOUNT"); | ||
| astriaWithdrawer.withdrawToSequencer{value: amount}(destinationChainAddress); | ||
|
|
||
| vm.stopBroadcast(); | ||
| } | ||
|
|
||
| function withdrawToOriginChain() public { | ||
| uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); | ||
| vm.startBroadcast(deployerPrivateKey); | ||
|
|
||
| address contractAddress = vm.envAddress("ASTRIA_WITHDRAWER"); | ||
| AstriaWithdrawer astriaWithdrawer = AstriaWithdrawer(contractAddress); | ||
|
|
||
| string memory destinationChainAddress = vm.envString("ORIGIN_DESTINATION_CHAIN_ADDRESS"); | ||
| uint256 amount = vm.envUint("AMOUNT"); | ||
| astriaWithdrawer.withdrawToOriginChain{value: amount}(destinationChainAddress, ""); | ||
|
|
||
| vm.stopBroadcast(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // SPDX-License-Identifier: MIT or Apache-2.0 | ||
| pragma solidity ^0.8.21; | ||
|
|
||
| // This contract facilitates withdrawals of the native asset from the rollup to the base chain. | ||
| // | ||
| // Funds can be withdrawn to either the sequencer or the origin chain via IBC. | ||
| contract AstriaWithdrawer { | ||
| // the number of decimal places more the asset has on the rollup versus the base chain. | ||
| // | ||
| // the amount transferred on the base chain will be divided by 10^ASSET_WITHDRAWAL_DECIMALS. | ||
| // | ||
| // for example, if the rollup specifies the asset has 18 decimal places and the base chain specifies 6, | ||
| // the ASSET_WITHDRAWAL_DECIMALS would be 12. | ||
| uint32 public immutable ASSET_WITHDRAWAL_DECIMALS; | ||
|
|
||
| constructor(uint32 assetWithdrawalDecimals) { | ||
| ASSET_WITHDRAWAL_DECIMALS = assetWithdrawalDecimals; | ||
| } | ||
|
|
||
| // emitted when a withdrawal to the sequencer is initiated | ||
| // | ||
| // the `sender` is the evm address that initiated the withdrawal | ||
| // the `destinationChainAddress` is the address on the sequencer the funds will be sent to | ||
| event SequencerWithdrawal(address indexed sender, uint256 indexed amount, address destinationChainAddress); | ||
|
|
||
| // emitted when a withdrawal to the origin chain is initiated. | ||
| // the withdrawal is sent to the origin chain via IBC from the sequencer using the denomination trace. | ||
| // | ||
| // the `sender` is the evm address that initiated the withdrawal | ||
| // the `destinationChainAddress` is the address on the origin chain the funds will be sent to | ||
| // the `memo` is an optional field that will be used as the ICS20 packet memo | ||
| event Ics20Withdrawal(address indexed sender, uint256 indexed amount, string destinationChainAddress, string memo); | ||
|
|
||
| function withdrawToSequencer(address destinationChainAddress) external payable { | ||
| emit SequencerWithdrawal(msg.sender, msg.value, destinationChainAddress); | ||
| } | ||
|
|
||
| function withdrawToOriginChain(string calldata destinationChainAddress, string calldata memo) external payable { | ||
| emit Ics20Withdrawal(msg.sender, msg.value, destinationChainAddress, memo); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.