-
Notifications
You must be signed in to change notification settings - Fork 9
implement AstriaMintableERC20, update deposit tx to support ERC20 mints
#20
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
64491c4
27d7b77
b4ed58b
d056553
a032bfc
2ad8943
1ef30ec
b04a771
fd9afd9
c99b5d2
563bd33
e21153d
239ff23
d6648d3
7511980
f66ae30
43fb433
f08e2e9
f1ac957
5d119e8
8f27bb9
c8feea2
7af66e1
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 |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| # Auto detect text files and perform LF normalization | ||
| * text=auto | ||
| *.sol linguist-language=Solidity | ||
|
|
||
| contracts/astria_bridgeable_erc20.go linguist-generated=true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,3 +50,6 @@ profile.cov | |
| logs/ | ||
|
|
||
| tests/spec-tests/ | ||
|
|
||
| contracts/abi | ||
| contracts/bin | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| # astria bridgeable erc20s | ||
|
|
||
| Package for the `AstriaBridgeableERC20` contract. | ||
|
|
||
| ## Initializing | ||
|
|
||
| Requirements: | ||
|
|
||
| - foundry | ||
|
|
||
| Build: | ||
|
|
||
| ```sh | ||
| git submodule update --init --recursive | ||
| cd astria-bridge-contracts | ||
| forge build | ||
| ``` | ||
|
|
||
| ## Go bindings | ||
|
|
||
| If you change the contract and wish to update the go bindings, run: | ||
|
|
||
| ```sh | ||
| chmod +x | ||
| ./generate-bindings.sh | ||
| ``` | ||
|
|
||
| ## Testing | ||
|
|
||
| To test the full end-to-end flow, run the sequencer, cometbft, composer, and conductor. Ensure the configured chain IDs are correct. | ||
|
|
||
| Copy the example .env: | ||
|
|
||
| ```sh | ||
| cp local.env.example .env && source .env | ||
| ``` | ||
|
|
||
| Deploy `AstriaBridgeableERC20.sol`: | ||
|
|
||
| ```sh | ||
| forge script script/AstriaBridgeableERC20.s.sol:AstriaBridgeableERC20Script \ | ||
| --rpc-url $RPC_URL --broadcast --sig "deploy()" -vvvv | ||
| ``` | ||
|
|
||
| Take note of the deployed address. | ||
|
|
||
| Add the following to the genesis file under `astriaBridgeAddresses`: | ||
|
|
||
| ```json | ||
| "astriaBridgeAddresses": [ | ||
| { | ||
| "bridgeAddress": "0x1c0c490f1b5528d8173c5de46d131160e4b2c0c3", | ||
| "startHeight": 1, | ||
| "assetDenom": "nria", | ||
| "assetPrecision": 6, | ||
| "erc20asset": { | ||
| "contractAddress":"0x9Aae647A1CB2ec6b39afd552aD149F6A26Bb2aD6", | ||
| "contractPrecision": 18 | ||
| } | ||
| } | ||
| ], | ||
| ``` | ||
|
|
||
| Note: this mints `nria` as an erc20 instead of the native asset. | ||
|
|
||
| `bridgeAddress` is the bridge address that corresponds to this asset on the sequencer chain. | ||
| `assetDenom` does not need to match the name of the token in the deployed contract, but it does need to match the denom of the token on the sequencer. | ||
| `contractAddress` in `erc20asset` is the address of the contract deployed above. | ||
|
|
||
| Stop the geth node and rerun `geth init --genesis genesis.json`. Restart the node. The contract is now initialized as a bridge from the sequencer. | ||
|
|
||
| Run the following with the `astria-cli`: | ||
|
|
||
| ```sh | ||
| # this matches the `bridgeAddress` 0x1c0c490f1b5528d8173c5de46d131160e4b2c0c3 in the genesis above | ||
| export SEQUENCER_PRIVATE_KEY=2bd806c97f0e00af1a1fc3328fa763a9269723c8db8fac4f93af71db186d6e90 | ||
| ./target/debug/astria-cli sequencer init-bridge-account --sequencer-url=http://localhost:26657 --rollup-name=astria | ||
| # the `destination-chain-address` matches the `PRIVATE_KEY` in local.example.env | ||
| ./target/debug/astria-cli sequencer bridge-lock --sequencer-url=http://localhost:26657 --amount=1000000 --destination-chain-address=0x46B77EFDFB20979E1C29ec98DcE73e3eCbF64102 --sequencer.chain-id=astria -- 1c0c490f1b5528d8173c5de46d131160e4b2c0c3 | ||
| ``` | ||
|
|
||
| This initializes the bridge account and also transfer funds over. | ||
|
|
||
| Check your ERC20 balance: | ||
|
|
||
| ```sh | ||
| forge script script/AstriaBridgeableERC20.s.sol:AstriaBridgeableERC20Script \ | ||
| --rpc-url $RPC_URL --sig "getBalance()" -vvvv | ||
| ``` | ||
|
|
||
| If everything worked, you should see a balance logged: | ||
| ``` | ||
| == Logs == | ||
| 1000000000000000000 | ||
| ``` |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| solc --optimize --optimize-runs=200 \ | ||
| --metadata --metadata-literal \ | ||
| --base-path "astria-bridge-contracts" \ | ||
| --abi "astria-bridge-contracts/src/AstriaBridgeableERC20.sol" \ | ||
| -o abi/ --overwrite | ||
|
|
||
| solc --optimize --optimize-runs=200 \ | ||
| --base-path "astria-bridge-contracts" \ | ||
| --bin "astria-bridge-contracts/src/AstriaBridgeableERC20.sol" \ | ||
| -o bin/ --overwrite | ||
|
|
||
| abigen --abi abi/AstriaBridgeableERC20.abi --bin bin/AstriaBridgeableERC20.bin --pkg contracts --type AstriaBridgeableERC20 --out astria_bridgeable_erc20.go |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,7 +48,9 @@ type ExecutionServiceServerV1Alpha2 struct { | |
|
|
||
| bridgeAddresses map[string]*params.AstriaBridgeAddressConfig // astria bridge addess to config for that bridge account | ||
| bridgeAllowedAssetIDs map[[32]byte]struct{} // a set of allowed asset IDs structs are left empty | ||
| nextFeeRecipient common.Address // Fee recipient for the next block | ||
| bridgeSenderAddress common.Address // address from which AstriaBridgeableERC20 contracts are called | ||
|
|
||
| nextFeeRecipient common.Address // Fee recipient for the next block | ||
| } | ||
|
|
||
| var ( | ||
|
|
@@ -104,16 +106,25 @@ func NewExecutionServiceServerV1Alpha2(eth *eth.Ethereum) (*ExecutionServiceServ | |
| return nil, fmt.Errorf("invalid bridge address config: %w", err) | ||
| } | ||
|
|
||
| if cfg.Erc20Asset != nil && nativeBridgeSeen { | ||
| return nil, errors.New("only one native bridge address is allowed") | ||
| } | ||
| if cfg.Erc20Asset != nil && !nativeBridgeSeen { | ||
| if cfg.Erc20Asset == nil { | ||
| if nativeBridgeSeen { | ||
| return nil, errors.New("only one native bridge address is allowed") | ||
| } | ||
| nativeBridgeSeen = true | ||
| } | ||
|
|
||
| if cfg.Erc20Asset != nil && bc.Config().AstriaBridgeSenderAddress == (common.Address{}) { | ||
| return nil, errors.New("astria bridge sender address must be set for bridged ERC20 assets") | ||
|
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. Noted further down, but we should probably use string.
Contributor
Author
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.
|
||
| } | ||
|
|
||
| bridgeAddresses[string(cfg.BridgeAddress)] = &cfg | ||
| assetID := sha256.Sum256([]byte(cfg.AssetDenom)) | ||
| bridgeAllowedAssetIDs[assetID] = struct{}{} | ||
| if cfg.Erc20Asset == nil { | ||
| log.Info("bridge for sequencer native asset initialized", "bridgeAddress", cfg.BridgeAddress, "assetDenom", cfg.AssetDenom) | ||
| } else { | ||
| log.Info("bridge for ERC20 asset initialized", "bridgeAddress", cfg.BridgeAddress, "assetDenom", cfg.AssetDenom, "contractAddress", cfg.Erc20Asset.ContractAddress) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -142,6 +153,7 @@ func NewExecutionServiceServerV1Alpha2(eth *eth.Ethereum) (*ExecutionServiceServ | |
| bc: bc, | ||
| bridgeAddresses: bridgeAddresses, | ||
| bridgeAllowedAssetIDs: bridgeAllowedAssetIDs, | ||
| bridgeSenderAddress: bc.Config().AstriaBridgeSenderAddress, | ||
| nextFeeRecipient: nextFeeRecipient, | ||
| }, nil | ||
| } | ||
|
|
@@ -237,9 +249,12 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req * | |
| return nil, status.Error(codes.FailedPrecondition, "Block can only be created on top of soft block.") | ||
| } | ||
|
|
||
| // the height that this block will be at | ||
| height := s.bc.CurrentBlock().Number.Uint64() + 1 | ||
|
|
||
| txsToProcess := types.Transactions{} | ||
| for _, tx := range req.Transactions { | ||
| unmarshalledTx, err := validateAndUnmarshalSequencerTx(tx, s.bridgeAddresses, s.bridgeAllowedAssetIDs) | ||
| unmarshalledTx, err := validateAndUnmarshalSequencerTx(height, tx, s.bridgeAddresses, s.bridgeAllowedAssetIDs, s.bridgeSenderAddress) | ||
| if err != nil { | ||
| log.Debug("failed to validate sequencer tx, ignoring", "tx", tx, "err", err) | ||
| continue | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how were we identifying the correct account to send funds to previously?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using the
Fromfield, but i felt that was confusing, and now we need to set theFromfield to the bridge "account"