Skip to content

implement AstriaWithdrawer contract and ethereum watcher#1086

Merged
noot merged 10 commits intoitamarreif/bridge-scaffoldingfrom
noot/withdrawer-eth-watcher
May 22, 2024
Merged

implement AstriaWithdrawer contract and ethereum watcher#1086
noot merged 10 commits intoitamarreif/bridge-scaffoldingfrom
noot/withdrawer-eth-watcher

Conversation

@noot
Copy link
Contributor

@noot noot commented May 20, 2024

Summary

implement ethereum module for astria-bridge-withdrawer.

Background

required to read from the astria withdrawal evm contract.

Changes

  • implement AstriaWithdrawer.sol contract, put inside ethereum/ dir as a foundry project
  • implement ethereum module which contains a Watcher that watches the contract for Withdrawal events
  • the events are sent to a Batcher which batches all events by block number and sends a batch of events to a sequencer handler (to be implemented later)

Testing

unit tests

Related Issues

#913

@github-actions github-actions bot added the ci issues that are related to ci and github workflows label May 21, 2024
@noot noot marked this pull request as ready for review May 21, 2024 20:52
@noot noot requested review from a team, SuperFluffy and joroshiba as code owners May 21, 2024 20:52
@@ -0,0 +1 @@
{"abi":[{"type":"function","name":"withdraw","inputs":[{"name":"memo","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"event","name":"Withdrawal","inputs":[{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"memo","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false}],"bytecode":{"object":"0x608060405234801561001057600080fd5b50610157806100206000396000f3fe60806040526004361061001e5760003560e01c80630968f26414610023575b600080fd5b610036610031366004610080565b610038565b005b34336001600160a01b03167f180489ed98391c12b0b024acb7dcd85ce43619bcf0780aeca68aa3dd44651a5d84846040516100749291906100f2565b60405180910390a35050565b6000806020838503121561009357600080fd5b823567ffffffffffffffff808211156100ab57600080fd5b818501915085601f8301126100bf57600080fd5b8135818111156100ce57600080fd5b8660208285010111156100e057600080fd5b60209290920196919550909350505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea26469706673582212201aaa74e63d8536d6bf6f782d9c2d7970b155e0ee1b1c634d3f0ac53f62c7dc2f64736f6c63430008150033","sourceMap":"72:238:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361061001e5760003560e01c80630968f26414610023575b600080fd5b610036610031366004610080565b610038565b005b34336001600160a01b03167f180489ed98391c12b0b024acb7dcd85ce43619bcf0780aeca68aa3dd44651a5d84846040516100749291906100f2565b60405180910390a35050565b6000806020838503121561009357600080fd5b823567ffffffffffffffff808211156100ab57600080fd5b818501915085601f8301126100bf57600080fd5b8135818111156100ce57600080fd5b8660208285010111156100e057600080fd5b60209290920196919550909350505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea26469706673582212201aaa74e63d8536d6bf6f782d9c2d7970b155e0ee1b1c634d3f0ac53f62c7dc2f64736f6c63430008150033","sourceMap":"72:238:0:-:0;;;;;;;;;;;;;;;;;;;;;191:117;;;;;;:::i;:::-;;:::i;:::-;;;285:9;273:10;-1:-1:-1;;;;;262:39:0;;296:4;;262:39;;;;;;;:::i;:::-;;;;;;;;191:117;;:::o;14:591:1:-;84:6;92;145:2;133:9;124:7;120:23;116:32;113:52;;;161:1;158;151:12;113:52;201:9;188:23;230:18;271:2;263:6;260:14;257:34;;;287:1;284;277:12;257:34;325:6;314:9;310:22;300:32;;370:7;363:4;359:2;355:13;351:27;341:55;;392:1;389;382:12;341:55;432:2;419:16;458:2;450:6;447:14;444:34;;;474:1;471;464:12;444:34;519:7;514:2;505:6;501:2;497:15;493:24;490:37;487:57;;;540:1;537;530:12;487:57;571:2;563:11;;;;;593:6;;-1:-1:-1;14:591:1;;-1:-1:-1;;;;14:591:1:o;610:388::-;767:2;756:9;749:21;806:6;801:2;790:9;786:18;779:34;863:6;855;850:2;839:9;835:18;822:48;919:1;890:22;;;914:2;886:31;;;879:42;;;;982:2;961:15;;;-1:-1:-1;;957:29:1;942:45;938:54;;610:388;-1:-1:-1;610:388:1:o","linkReferences":{}},"methodIdentifiers":{"withdraw(bytes)":"0968f264"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"memo\",\"type\":\"bytes\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"memo\",\"type\":\"bytes\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/AstriaWithdrawer.sol\":\"AstriaWithdrawer\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":forge-std/=lib/forge-std/src/\"]},\"sources\":{\"src/AstriaWithdrawer.sol\":{\"keccak256\":\"0x28b6cd3c3296777530089b7c1c930e63addfe7b7267b7a4053a4a241d41444cb\",\"license\":\"MIT or Apache-2.0\",\"urls\":[\"bzz-raw://d868517107f12a1290c818458943bfe1fccd981848f07260528d56cbbb756649\",\"dweb:/ipfs/QmfSWtY3vEaFc6okLAvwVaGRN6paDNAGovTD3f94oTBJeR\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.21+commit.d9974bed"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"sender","type":"address","indexed":true},{"internalType":"uint256","name":"amount","type":"uint256","indexed":true},{"internalType":"bytes","name":"memo","type":"bytes","indexed":false}],"type":"event","name":"Withdrawal","anonymous":false},{"inputs":[{"internalType":"bytes","name":"memo","type":"bytes"}],"stateMutability":"payable","type":"function","name":"withdraw"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["forge-std/=lib/forge-std/src/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/AstriaWithdrawer.sol":"AstriaWithdrawer"},"evmVersion":"paris","libraries":{}},"sources":{"src/AstriaWithdrawer.sol":{"keccak256":"0x28b6cd3c3296777530089b7c1c930e63addfe7b7267b7a4053a4a241d41444cb","urls":["bzz-raw://d868517107f12a1290c818458943bfe1fccd981848f07260528d56cbbb756649","dweb:/ipfs/QmfSWtY3vEaFc6okLAvwVaGRN6paDNAGovTD3f94oTBJeR"],"license":"MIT or Apache-2.0"}},"version":1},"ast":{"absolutePath":"src/AstriaWithdrawer.sol","id":25,"exportedSymbols":{"AstriaWithdrawer":[24]},"nodeType":"SourceUnit","src":"46:265:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"46:24:0","nodes":[],"literals":["solidity","^","0.8",".21"]},{"id":24,"nodeType":"ContractDefinition","src":"72:238:0","nodes":[{"id":9,"nodeType":"EventDefinition","src":"104:77:0","nodes":[],"anonymous":false,"eventSelector":"180489ed98391c12b0b024acb7dcd85ce43619bcf0780aeca68aa3dd44651a5d","name":"Withdrawal","nameLocation":"110:10:0","parameters":{"id":8,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"indexed":true,"mutability":"mutable","name":"sender","nameLocation":"137:6:0","nodeType":"VariableDeclaration","scope":9,"src":"121:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":2,"name":"address","nodeType":"ElementaryTypeName","src":"121:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":5,"indexed":true,"mutability":"mutable","name":"amount","nameLocation":"161:6:0","nodeType":"VariableDeclaration","scope":9,"src":"145:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":4,"name":"uint256","nodeType":"ElementaryTypeName","src":"145:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"},{"constant":false,"id":7,"indexed":false,"mutability":"mutable","name":"memo","nameLocation":"175:4:0","nodeType":"VariableDeclaration","scope":9,"src":"169:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":6,"name":"bytes","nodeType":"ElementaryTypeName","src":"169:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"120:60:0"}},{"id":23,"nodeType":"FunctionDefinition","src":"191:117:0","nodes":[],"body":{"id":22,"nodeType":"Block","src":"247:61:0","nodes":[],"statements":[{"eventCall":{"arguments":[{"expression":{"id":15,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"273:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":16,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"277:6:0","memberName":"sender","nodeType":"MemberAccess","src":"273:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},{"expression":{"id":17,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"285:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":18,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"289:5:0","memberName":"value","nodeType":"MemberAccess","src":"285:9:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},{"id":19,"name":"memo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":11,"src":"296:4:0","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"},{"typeIdentifier":"t_uint256","typeString":"uint256"},{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}],"id":14,"name":"Withdrawal","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9,"src":"262:10:0","typeDescriptions":{"typeIdentifier":"t_function_event_nonpayable$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$__$","typeString":"function (address,uint256,bytes memory)"}},"id":20,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"262:39:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":21,"nodeType":"EmitStatement","src":"257:44:0"}]},"functionSelector":"0968f264","implemented":true,"kind":"function","modifiers":[],"name":"withdraw","nameLocation":"200:8:0","parameters":{"id":12,"nodeType":"ParameterList","parameters":[{"constant":false,"id":11,"mutability":"mutable","name":"memo","nameLocation":"224:4:0","nodeType":"VariableDeclaration","scope":23,"src":"209:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":10,"name":"bytes","nodeType":"ElementaryTypeName","src":"209:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"208:21:0"},"returnParameters":{"id":13,"nodeType":"ParameterList","parameters":[],"src":"247:0:0"},"scope":24,"stateMutability":"payable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"AstriaWithdrawer","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[24],"name":"AstriaWithdrawer","nameLocation":"81:16:0","scope":25,"usedErrors":[],"usedEvents":[9]}],"license":"MIT or Apache-2.0"},"id":0} No newline at end of file
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i committed this because otherwise we have to install foundry in ci which was painful last time - however this will need to be updated if the contract changes. thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree - its nicer to have these committed rather than having to deal with with foundry every time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely agreed here

Copy link
Contributor

@itamarreif itamarreif left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only thing that sticks out to me is back pressure:

  • both the watcher->batcher and the batcher->submitter channels have capacity of 100
  • both use send() instead of send_timeout()
  • submitter logic will use broadcast_tx_commit so might take a bit of time in the event of a congested mempool on the sequencer side
  • if withdraws for 100 entire blocks clog up the batcher->submitter channel, the next 100 individual withdraws will clog up the watcher->batcher channel

doesn't seem like too big of a problem if we choose the right values for channel sizes (100 is probably fine) but figured it would be useful to flag and maybe clarify somewhere in the documentation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also need information on how to initialize the submodule?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think forge build should automatically do it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the submodule? Could one use forge to install forge-std?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this is just how foundry is set up, forge build should install everything. we don't use the forge-std deps right now but if we want to add solidity unit tests we will

@noot
Copy link
Contributor Author

noot commented May 22, 2024

doesn't seem like too big of a problem if we choose the right values for channel sizes (100 is probably fine) but figured it would be useful to flag and maybe clarify somewhere in the documentation

yeah this is pretty arbitrary, i just picked a random number basically. i suppose the watcher->batcher channel will probably have more items than the batcher->submitter, so maybe the value for that should be higher. i can add a comment for now saying the values are arbitrary

both use send() instead of send_timeout()

i think send_timeout would be kinda bad, since we want to guarantee 1 eth block of withdrawals -> 1 sequencer tx without missing any, if there's timeouts there's a chance a tx within the block could be missed? i'd prefer that if anything fails to send, we just error at this point. not against timeouts but depends how we implement tracking txs that have been submitted

@noot noot merged commit 6b3e883 into itamarreif/bridge-scaffolding May 22, 2024
@noot noot deleted the noot/withdrawer-eth-watcher branch May 22, 2024 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci issues that are related to ci and github workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants