From d20a3a556395390570c390d5259c34f8bd282b7a Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:49:08 +0100 Subject: [PATCH 1/6] feat : helper functions to deploy Hub & Spoke for external codebases --- Makefile | 20 ++++++++++-- foundry.toml | 6 +++- scripts/utils/GenerateBytecodeScript.s.sol | 19 ++++++++++++ tests/DeployUtils.sol | 1 + tests/bin/hub.bytecode | Bin 0 -> 23707 bytes tests/bin/spokeInstance.bytecode | 1 + tests/unit/scripts/GenerateBytecode.t.sol | 34 +++++++++++++++++++++ tests/utils/BytecodeLoader.sol | 32 +++++++++++++++++++ tests/utils/DeployHub.sol | 22 +++++++++++++ tests/utils/DeploySpoke.sol | 32 +++++++++++++++++++ 10 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 scripts/utils/GenerateBytecodeScript.s.sol create mode 100644 tests/bin/hub.bytecode create mode 100644 tests/bin/spokeInstance.bytecode create mode 100644 tests/unit/scripts/GenerateBytecode.t.sol create mode 100644 tests/utils/BytecodeLoader.sol create mode 100644 tests/utils/DeployHub.sol create mode 100644 tests/utils/DeploySpoke.sol diff --git a/Makefile b/Makefile index 9081609b9..10820bb85 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,19 @@ update:; forge update # Build & test -build :; forge build --sizes -test :; forge test -vvv +build-simple :; forge build +build-simple-sizes :; forge build --sizes +test-simple :; forge test -vvv +generate :; forge script scripts/utils/GenerateBytecodeScript.s.sol +build : + make build-simple + make generate +build-sizes : + make build-simple-sizes + make generate +test : + make build + make test-simple # Utilities download :; cast etherscan-source --chain ${chain} -d src/etherscan/${chain}_${address} ${address} @@ -16,7 +27,10 @@ git-diff : @npx prettier ${before} ${after} --write @printf '%s\n%s\n%s\n' "\`\`\`diff" "$$(git diff --no-index --diff-algorithm=patience --ignore-space-at-eol ${before} ${after})" "\`\`\`" > diffs/${out}.md -gas-report :; forge test --mp 'tests/gas/**' +gas-report : + make build + make test-gas-report +test-gas-report :; forge test --mp 'tests/gas/**' # Coverage coverage-base :; FOUNDRY_PROFILE=coverage forge coverage --report lcov --no-match-coverage "(scripts|tests|deployments|mocks)" diff --git a/foundry.toml b/foundry.toml index 4fdd4cf5b..117ef1c65 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,7 +3,11 @@ src = 'src' test = 'tests' out = 'out' libs = ['lib'] -fs_permissions = [{ access = "read", path = "tests/mocks/JsonBindings.sol" }] +fs_permissions = [ + { access = "read", path = "tests/mocks/JsonBindings.sol" }, + { access = "read-write", path = "./tests/bin" }, + { access = "read", path = "out/" } +] solc_version = "0.8.28" evm_version = "cancun" optimizer = true diff --git a/scripts/utils/GenerateBytecodeScript.s.sol b/scripts/utils/GenerateBytecodeScript.s.sol new file mode 100644 index 000000000..23f54ee68 --- /dev/null +++ b/scripts/utils/GenerateBytecodeScript.s.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Script} from 'forge-std/Script.sol'; + +contract GenerateHubBytecodeScript is Script { + string private constant HUB_BYTECODE_PATH = 'tests/bin/hub.bytecode'; + string private constant SPOKE_INSTANCE_BYTECODE_PATH = 'tests/bin/spokeInstance.bytecode'; + + function run() external { + bytes memory hubBytecode = vm.getCode('src/hub/Hub.sol:Hub'); + vm.writeFileBinary(HUB_BYTECODE_PATH, hubBytecode); + + string memory artifact = vm.readFile('out/SpokeInstance.sol/SpokeInstance.json'); + string memory spokeHex = vm.parseJsonString(artifact, '.bytecode.object'); + vm.writeFile(SPOKE_INSTANCE_BYTECODE_PATH, spokeHex); + } +} diff --git a/tests/DeployUtils.sol b/tests/DeployUtils.sol index e928effd6..22c4021b0 100644 --- a/tests/DeployUtils.sol +++ b/tests/DeployUtils.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import {Vm} from 'forge-std/Vm.sol'; + import {TransparentUpgradeableProxy} from 'src/dependencies/openzeppelin/TransparentUpgradeableProxy.sol'; import {IHub} from 'src/hub/interfaces/IHub.sol'; import {ISpoke} from 'src/spoke/interfaces/ISpoke.sol'; diff --git a/tests/bin/hub.bytecode b/tests/bin/hub.bytecode new file mode 100644 index 0000000000000000000000000000000000000000..b97c91427c35d6a1f00569da44f18eb43beb038c GIT binary patch literal 23707 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

!}+0kg~kH0F6 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

HDU~)( zRG5Se3tnIC@DZ0{M$vsT%+zavPdaTt!Y;ld^dQt-0cT9an7;4a{eQjg{+Hgl?aYQ3 z<$qii+;dUM)?414Rek8x*S>t^strc2lu_+qBZLccC0h(hPkzP8#Pg_1<8I2L+CqjI znyZ!9%DUl4!&?w(5~1ipJGmac73)Eiu|Nm9Ia2F0EtkA{nNgU)RpOFYqom}9fxG54 zk*WN0wuhjbXTgj}xYF{`q>Sl?&VPv~OM|ZB)0NHM#HT*+z-1uh!50=@v*5X_9_0>)`3*j)9nthqTA zD$0@Bc5au&5uMojK0lTV!zyY}>kDBn*7+ircRu|4vM8uF>}&rQ&l zTG~Hb@` z?lnItWWZY}w%g6+A#M4*E||0mEQT-0OQMv! zf-`LSE%)%p>aV%5Jg+Oq4W~g<&_$Ih+B#A+y7w2&gC@`AG*S`Q*m_wwCOi6d-hwRQ zu!KxBqHaq$<~L$>4B8r3w1g0r@Nd%AeY|3N6!2I)9}eDBWu^faG2KJLK6!| literal 0 HcmV?d00001 diff --git a/tests/bin/spokeInstance.bytecode b/tests/bin/spokeInstance.bytecode new file mode 100644 index 000000000..f24005d1d --- /dev/null +++ b/tests/bin/spokeInstance.bytecode @@ -0,0 +1 @@ +0x61016080604052346102b85760408161620a803803809161002082856102cf565b8339810103126102b85780516001600160a01b038116918282036102b857602001519161ffff8316908184036102b8576020600491306080524660a05260a060405161006d6040826102cf565b60058152838101906453706f6b6560d81b82526040519161008f6040846102cf565b6001835285830191603160f81b8352519020915190208160c0528060e052604051917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8352858301526040820152466060820152306080820152206101005260405192838092632e0f262560e01b82525afa9081156102c4575f91610283575b5060ff600891160361027457156102655761014052610120525f5160206161ea5f395f51905f525460ff8160401c16610256576002600160401b03196001600160401b03821601610200575b604051615ee390816103078239608051818181610b360152613de1015260a051818181610b130152613dbe015260c051818181610b980152613e92015260e051818181610bbe0152613eb8015261010051818181610af10152613d9c015261012051818181610c5601528181612a4c015281816138000152613af5015261014051818181610c18015281816125c801528181613b44015281816146750152614e160152f35b6001600160401b0319166001600160401b039081175f5160206161ea5f395f51905f52556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f61015b565b63f92ee8a960e01b5f5260045ffd5b63bdf3f56360e01b5f5260045ffd5b631c5f5f5d60e11b5f5260045ffd5b90506020813d6020116102bc575b8161029e602093836102cf565b810103126102b8575160ff811681036102b85760ff61010f565b5f80fd5b3d9150610291565b6040513d5f823e3d90fd5b601f909101601f19168101906001600160401b038211908210176102f257604052565b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c80628754a2146103a357806303ed05c11461039e5780630ad58d2f146103995780631cdc762c14610394578063238b26d31461038f5780632630faab1461038a5780632bccdfd5146103855780632fa08544146103805780632fd005271461037b5780633644e5151461037657806338013f02146103715780633d59ce761461036c57806342aef1f11461036757806346fbf741146103625780634de8d2ba1461035d5780636a3b37da146103585780637445fb161461035357806377778db31461034e5780637784c685146103495780637a9e5e4b14610344578063826002e21461033f57806384b0196e1461033a578063852a56a514610335578063869da9db1461033057806387107a6d1461032b5780638874e104146103265780638fb3603714610321578063911a34131461031c57806391c46d09146103175780639290fa001461031257806393eff7a81461030d57806399806546146103085780639b7172a6146103035780639ca9c134146102fe5780639e35c533146102f9578063a0f5b9ab146102f4578063a2a522f1146102ef578063aaaf97ab146102ea578063ac177f1b146102e5578063ac9650d8146102e0578063b1e8f8ef146102db578063b2380e93146102d6578063bef37613146102d1578063bf7e214f146102cc578063bf92857c146102c7578063c2fa746c146102c2578063c4d66de8146102bd578063ce603521146102b8578063d6bda0c0146102b3578063d86b407f146102ae578063e0fd5c5c146102a9578063e8dccc22146102a4578063e903e1bd1461029f578063ec17bb001461029a578063f1568a8914610295578063f6acf369146102905763fea149a61461028b575f80fd5b612e2b565b612df1565b612d4c565b612c94565b612b90565b612b67565b612b0c565b612adc565b6128ba565b612860565b61272a565b612566565b6124e8565b6124b6565b612409565b6123d0565b6120f2565b612031565b611f9b565b611f7c565b611ee3565b611de4565b611d9a565b611d25565b611ced565b611cd1565b611c28565b611aef565b611a95565b611a5e565b611a0e565b6119f5565b6118df565b6117b4565b611613565b611575565b6114d5565b61145c565b61141f565b611310565b6111f9565b6111b5565b610e7c565b610cd6565b610c7a565b610c3c565b610bf9565b610adf565b610a7b565b610a16565b61092a565b6108e1565b61089d565b610801565b610556565b6104a0565b3461049c57602036600319011261049c5761049860016103cd6004356103c7612f38565b50613cec565b015461045060ff8260d01c166104476103e882600116151590565b9161043e6103fe60028316151592600416151590565b91610435600860d089901c1615159561042c62ffffff61041c612efb565b9a60b81c168a9062ffffff169052565b15156020890152565b15156040870152565b15156060850152565b15156080830152565b6040519182918291909160808060a083019462ffffff815116845260208101511515602085015260408101511515604085015260608101511515606085015201511515910152565b0390f35b5f80fd5b3461049c57604036600319011261049c5760043567ffffffffffffffff811161049c576080600319823603011261049c576024359067ffffffffffffffff821161049c573660238301121561049c5781600401359067ffffffffffffffff821161049c57366024838501011161049c576024610520930190600401612fd5565b005b6001600160a01b0381160361049c57565b606090600319011261049c57600435906024359060443561055381610522565b90565b3461049c5761056436610533565b909161056e613f6a565b61058061057b3384613fea565b61318f565b61058981613cec565b9160016105b8836105ab846001600160a01b03165f52600660205260405f2090565b905f5260205260405f2090565b930154936105d160d086901c60ff16614064565b614064565b60026001600160a01b036105f66105ef8883169860a01c61ffff1690565b61ffff1690565b9616940190610641602061061184546001600160781b031690565b6040516360268b2760e11b8152600481018a90526001600160781b03909116602482015291829081906044820190565b0381895afa9586156107dd575f966020936106989389926107e2575b5060405163e840427d60e01b8152600481019a909a528082189082110218602489018190523360448a01529796879283919082906064820190565b03925af19384156107dd575f946107a8575b506106e5906106cb6106bb86614071565b82546001600160781b03166131d2565b6001600160781b03166001600160781b0319825416179055565b61072582610704836001600160a01b03165f52600560205260405f2090565b906001918160071c5f526020528160fe60405f205492821b16011c16151590565b610790575b6001600160a01b036040519116917ffe7813e2866053d5c3938554e517b554fce6666a6561bed9eaa7419b29fa9b6833928061077488888360209093929193604081019481520152565b0390a461077f613fc5565b604080519182526020820192909252f35b6107a361079c826140a2565b5182614159565b61072a565b6106e59194506107cf9060203d6020116107d6575b6107c78183612ed9565b8101906131a4565b93906106aa565b503d6107bd565b6131b3565b6107fa919250853d87116107d6576107c78183612ed9565b905f61065d565b3461049c57602036600319011261049c57600161081f600435613cec565b01546040516303bf6e9f60e61b815260a082901c61ffff166004820152306024820152906020908290816001600160a01b0381604481015b0392165afa80156107dd57610498915f9161087e575b506040519081529081906020820190565b610897915060203d6020116107d6576107c78183612ed9565b5f61086d565b3461049c57602036600319011261049c576001600160a01b036004356108c281610522565b165f526005602052602062ffffff600160405f20015416604051908152f35b3461049c57604036600319011261049c57602061091560043561090381610522565b6024359061091082610522565b613fea565b6040519015158152f35b60ff81160361049c57565b3461049c5760e036600319011261049c5760243560043561094a82610522565b608435916064359060443561095e8561091f565b60a435936001600160a01b0361098f61098260c435935f52600260205260405f2090565b546001600160a01b031690565b169261099c8415156131f2565b833b1561049c5760405163d505accf60e01b81526001600160a01b0390911660048201523060248201526044810192909252606482019390935260ff909416608485015260a484019290925260c48301525f90829081838160e4810103925af1610a0257005b80610a105f61052093612ed9565b80610ad5565b3461049c57604036600319011261049c576004356001600160a01b03602435610a3e81610522565b610a4783613cec565b50165f52600660205260405f20905f526020526001600160781b03600260405f200154166040518091602082019082520390f35b3461049c57602036600319011261049c576001610a99600435613cec565b0154604051639c7ee64f60e01b815260a082901c61ffff166004820152306024820152906020908290816001600160a01b038160448101610857565b5f91031261049c57565b3461049c575f36600319011261049c577f0000000000000000000000000000000000000000000000000000000000000000467f000000000000000000000000000000000000000000000000000000000000000014307f0000000000000000000000000000000000000000000000000000000000000000141615610b68575b602090604051908152f35b506020610bf260a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201524660608201523060808201522090565b9050610b5d565b3461049c575f36600319011261049c5760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461049c575f36600319011261049c57602060405161ffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461049c57604036600319011261049c576020600435610c9981610522565b610cce610cc9602435926001600160a01b0381165f526003855260405f20845f52855260405f205493849161435d565b6131f2565b604051908152f35b3461049c57606036600319011261049c57600435602067ffffffffffffffff602435610d0181610522565b610dda604435610d1086613cec565b50610d8d610d8060015494610d6e6002610d60610d328961ffff9060c01c1690565b9b6105ab610d48825f52600460205260405f2090565b956001600160a01b03165f52600660205260405f2090565b015460781c63ffffffff1690565b63ffffffff165f5260205260405f2090565b5460101c63ffffffff1690565b9060405196879586956301ca7c8960e61b875260801c1660048601929363ffffffff91959461ffff60609467ffffffffffffffff6080880199168752166020860152604085015216910152565b038173__$a48140799943db40fec4e369e92a011fa5$__5af480156107dd57610498915f9161087e57506040519081529081906020820190565b60a090606319011261049c57606490565b60a090602319011261049c57602490565b60609061010319011261049c5761010490565b606090600319011261049c57600490565b606090602319011261049c57602490565b606090604319011261049c57604490565b3461049c5761016036600319011261049c57600435610e9a81610522565b6105ab6024359160443592610eae84610522565b610eb736610e14565b610ec036610e36565b90610ecb363361441d565b6001600160a01b03841693610ee1851515613208565b610eef61ffff85111561321e565b610f28610f23610f1f610f17876105ab866001600160a01b03165f52600360205260405f2090565b54878561435d565b1590565b613234565b610f318261456a565b610f3a836145aa565b610f65845f54978893610f4c8561324a565b5f556001600160a01b03165f52600360205260405f2090565b556040805163de079b5760e01b815260048101859052929083602481885afa80156107dd577fe9495512a0eb05fe0cbdd52286bdeb54cb8e5a8d50e7e17d75f75903a98e2af886889661114a866110ee6104989d7ffcede5501ba87e3766118ae6ed360a87ee9b6570156ae9cac52d35ff0de0403b9a5f9d6111599b8f9a8f809c945f9261116c575b506110c7929161102986976110bb936110146001600160a01b036110d19a16151561327d565b611024601260ff86161115613293565b614655565b6110b16110358c61470b565b6110a661107b6110506020611049896132b6565b9801612fcb565b8d61105d60408201612fcb565b611075608061106e60608501612fcb565b9301612fcb565b92614732565b97611096611087612f0a565b6001600160a01b03909c168c52565b6001600160a01b031660208b0152565b61ffff166040890152565b60ff166060870152565b62ffffff166080850152565b60ff1660a0830152565b8c60c08201526110e9885f52600260205260405f2090565b6132c0565b61111987611114611107895f52600460205260405f2090565b5f805260205260405f2090565b613446565b604051938493877fb2d3221c3db1eb0d586556ae23399acdfe3e52ff0fcd184c19069c730f9ca2e98e80a4826134bb565b0390a260405191829182613529565b0390a36040519081529081906020820190565b6110d195506110c79392509061102961119f6110bb9360403d6040116111ae575b6111978183612ed9565b810190613258565b90975093945090919050610fee565b503d61118d565b3461049c57602036600319011261049c576001600160a01b036004356111da81610522565b165f526007602052602060ff600160405f200154166040519015158152f35b3461049c57604036600319011261049c576112826112676004355b6024359061122182610522565b6001600160a01b0361123282613cec565b92165f52600660205260405f20905f52602052600160405f20910154906001600160a01b0361ffff8360a01c16921690614781565b9190916b033b2e3c9fd0803ce8000000808206151591040190565b60408051928352602083019190915290f35b61130e9092919260c08060e08301956001600160a01b0381511684526001600160a01b03602082015116602085015261ffff604082015116604085015260ff606082015116606085015262ffffff608082015116608085015261130160a082015160a086019060ff169052565b015163ffffffff16910152565b565b3461049c57602036600319011261049c576104986113326004356103c7613570565b6113bf6113b260016040519361134785612e64565b6001600160a01b03815416855201546001600160a01b038116602085015261137d61ffff8260a01c16604086019061ffff169052565b60ff60b082901c16606085015262ffffff60b882901c16608085015260ff60d082901c1660a085015260d81c63ffffffff1690565b63ffffffff1660c0830152565b60405191829182611294565b90602060031983011261049c5760043567ffffffffffffffff811161049c5760040182601f8201121561049c5780359267ffffffffffffffff841161049c576020808301928560051b01011161049c579190565b3461049c5761142d366113cb565b60205f528060205260409060051b604001915b82821061144b57825ff35b803554825260209182019101611440565b3461049c57602036600319011261049c5760043561147981610522565b6001600160a01b035f516020615e975f395f51905f52541633036114c357803b156114a757610520906147e7565b6001600160a01b03906361798f2f60e11b5f521660045260245ffd5b62d1953b60e31b5f523360045260245ffd5b3461049c57602036600319011261049c5761151d6004356114f581610522565b6114fd613f6a565b6115073382613fea565b15611542575b611516816140a2565b5190614159565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d005b61154c363361441d565b61150d565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b3461049c575f36600319011261049c576115b46115c2611593614854565b604092919251938493600f60f81b855260e0602086015260e0850190611551565b908382036040850152611551565b4660608301523060808301525f60a083015281810360c083015260206060519182815201906080905f5b8181106115fa575050500390f35b82518452859450602093840193909201916001016115ec565b3461049c5761170761162436610533565b61163093929193613f6a565b61163d61057b3383613fea565b61164682613cec565b602085611668856105ab866001600160a01b03165f52600660205260405f2090565b926116b88260018301926116b06116976116a36116978754946109826116928760ff9060d01c1690565b6148a9565b6001600160a01b031690565b926001600160a01b031690565b9033906148c3565b546116d96116ce6001600160a01b038316611697565b9160a01c61ffff1690565b5f60405180998195829463771602f760e01b8452600484016020909392919361ffff60408201951681520152565b03925af19384156107dd575f9461178f575b50611745906106cb600261172c87614071565b92019161174083546001600160781b031690565b6135a6565b6001600160a01b036040519116917fd986db228cb1fe8392c5f45ff5f2c639b7db6cbd9ca7d1fe70b2de90c2c8c96133928061077488888360209093929193604081019481520152565b6117459194506117ad9060203d6020116107d6576107c78183612ed9565b9390611719565b3461049c57604036600319011261049c576004356001600160a01b036024356117dc81610522565b6117e4612f38565b506117ee83613cec565b50165f52600660205260405f20905f5260205261049860405f2061188061187360026040519361181d85612e85565b6001600160781b038154818116875260781c166020860152600181015460180b60408601520154611867611857826001600160781b031690565b6001600160781b03166060860152565b60781c63ffffffff1690565b63ffffffff166080830152565b60405191829182919091608063ffffffff8160a08401956001600160781b0381511685526001600160781b036020820151166020860152604081015160180b60408601526001600160781b036060820151166060860152015116910152565b3461049c57606036600319011261049c576118f936610e49565b611903363361441d565b670de0b6b3a76400006001600160801b03823561191f816135c6565b161015806119a9575b80611981575b156119725761196d816119617f9062eec1933c38394d82dc926d7ddcd777a5cd08e1ae6baa94e90047338d3459936135e9565b604051918291826136bd565b0390a1005b63a3f02e7f60e01b5f5260045ffd5b50670de0b6b3a764000067ffffffffffffffff60208301356119a2816135d7565b161061192e565b5061271061ffff60408301356119be8161343a565b161115611928565b8015150361049c57565b604090600319011261049c576004356119e881610522565b90602435610553816119c6565b3461049c57610520611a06366119d0565b903390613ef1565b3461049c575f36600319011261049c575f516020615e975f395f51905f525460a01c60ff1615611a56576020638fb3603760e01b5b6040516001600160e01b03199091168152f35b60205f611a43565b3461049c575f36600319011261049c5760206040516001600160a01b0373__$a48140799943db40fec4e369e92a011fa5$__168152f35b3461049c57602036600319011261049c5761151d600435611ab581610522565b611abd613f6a565b611ac73382613fea565b15611ae0575b611ad5613570565b506115165f82614dcf565b611aea363361441d565b611acd565b3461049c57608036600319011261049c57600435611b0c36610e5a565b90611b17363361441d565b611b235f5482106131f2565b805f52600260205263ffffffff600160405f20015460d81c169163ffffffff831015611c1957611b61600161049894611b5b846145aa565b0161495f565b91611b9c836001611b7a845f52600260205260405f2090565b019063ffffffff60d81b1982549163ffffffff60d81b9060d81b169116179055565b611bc98261111485611bb6855f52600460205260405f2090565b9063ffffffff165f5260205260405f2090565b7ffcede5501ba87e3766118ae6ed360a87ee9b6570156ae9cac52d35ff0de0403b60405180611bff63ffffffff87169582613529565b0390a360405163ffffffff90911681529081906020820190565b6322bfed3d60e21b5f5260045ffd5b3461049c57602036600319011261049c576001611c46600435613cec565b015460408051633c9a9ee560e01b815261ffff60a084901c16600482015230602482015291829060449082906001600160a01b03165afa9081156107dd575f905f92611c9f575b50604080519182526020820192909252f35b9050611cc3915060403d604011611cca575b611cbb8183612ed9565b8101906136f8565b905f611c8d565b503d611cb1565b3461049c575f36600319011261049c5760205f54604051908152f35b3461049c57604036600319011261049c57611d0c611267600435611214565b8101809111611d2057604051908152602090f35b6131be565b3461049c576001600160a01b037f8e04e916c2b397f8ab1cf9a55e94728a44837b3751f72369339ad991d371edc46020611d5e366119d0565b9390611d6a363361441d565b1692835f5260078252611d8f81600160405f20019060ff801983541691151516179055565b6040519015158152a2005b3461049c57606036600319011261049c5761151d600435602435611dbd816119c6565b60443591611dca83610522565b611dd2613f6a565b611ddf61057b3385613fea565b61371b565b3461049c5760c036600319011261049c576004357fe9495512a0eb05fe0cbdd52286bdeb54cb8e5a8d50e7e17d75f75903a98e2af8611ede611e2536610e25565b611e2f363361441d565b611ed2611e3b85613cec565b611e448361456a565b611e766001843592611e55846132a9565b0191829062ffffff60b81b1962ffffff60b81b83549260b81b169116179055565b611eb86020840135611e87816119c6565b6040850135611e95816119c6565b606086013590611ea4826119c6565b608087013592611eb3846119c6565b614732565b815460ff60d01b191660d09190911b60ff60d01b16179055565b604051918291826134bb565b0390a2005b3461049c57604036600319011261049c5760406004356001600160a01b03602435611f0d81610522565b611f1683613cec565b50165f526005602052611f6c825f2091611f4c8184906001918160071c5f526020528160fe60405f205492821b16011c16151590565b92906001918160071c5f5260205260fe60405f205491831b161c16151590565b8251911515825215156020820152f35b3461049c57602036600319011261049c57602060043554604051908152f35b3461049c57604036600319011261049c57610498611fc160243560043561122182610522565b604051908152918291506020820190565b602081016020825282518091526040820191602060408360051b8301019401925f915b83831061200457505050505090565b9091929394602080612022600193603f198682030187528951611551565b97019301930191939290611ff5565b3461049c5761203f366113cb565b906120498261384d565b916120576040519384612ed9565b808352601f196120668261384d565b015f5b8181106120e15750505f5b81811061208957604051806104988682611fd2565b5f80612096838587613865565b906120a6604051809381936138a7565b0390305af46120b36138d0565b90156120d957906001916120c782876138ff565b526120d281866138ff565b5001612074565b602081519101fd5b806060602080938801015201612069565b3461049c576121a461210336610533565b90929161210e613f6a565b61211b61057b3384613fea565b61212481613cec565b90612144816105ab856001600160a01b03165f52600660205260405f2090565b91600181019283549661215e6105cc8960ff9060d01c1690565b60206121806121756001600160a01b038b16611697565b9960a01c61ffff1690565b6040516316be8c1960e31b815261ffff909116600482015297889081906024820190565b03818b5afa9687156107dd575f976123ab575b506121c3908783614a51565b9490926121d08885614ac3565b97866121ed896001600160a01b03165f52600560205260405f2090565b6001015462ffffff1662ffffff16612206928b87614be8565b956b033b2e3c9fd0803ce80000008082049106151501612226908561370e565b809933925461223b906001600160a01b031690565b6001600160a01b03169261224e936148c3565b54846001600160a01b0382166001600160a01b03169160a01c61ffff16604051632a5b380360e01b8152948592839261228b929060048501613913565b03815a6020945f91f19081156107dd576001600160781b03926123089261238e575b506122b88582614caf565b6122fb6122d76122c789614071565b83546001600160781b03166131d2565b82546effffffffffffffffffffffffffffff19166001600160781b03909116178255565b546001600160781b031690565b161561234c575b7fd765a0263e8a360da8dd4fdb8c0dc5553adec12a96f29a462cdb45e5bea407dd6001600160a01b03604051941693806107743395898984613949565b6123898161236b856001600160a01b03165f52600560205260405f2090565b8160071c5f52602052600160fe60405f2092821b161b198154169055565b61230f565b6123a69060203d6020116107d6576107c78183612ed9565b6122ad565b6121c39197506123c99060203d6020116107d6576107c78183612ed9565b96906121b7565b3461049c57604036600319011261049c576105206024356004356123f382610522565b6123fd363361441d565b6110245f5482106131f2565b3461049c57604036600319011261049c5760043561242681610522565b602435906001600160c01b038216820361049c576020916001600160a01b03610cce92165f527f474d4a5585c1bae3dbeb574bb96408c7174aadd8ab635de4ab498e2723195f00835267ffffffffffffffff6124968260405f20906001600160c01b03165f5260205260405f2090565b541667ffffffffffffffff169067ffffffffffffffff199060401b161790565b3461049c575f36600319011261049c5760206001600160a01b035f516020615e975f395f51905f525416604051908152f35b3461049c57602036600319011261049c5760e061251b5f60043561250b81610522565b612513613570565b506001615e64565b612564604051809260c08091805184526020810151602085015260408101516040850152606081015160608501526080810151608085015260a081015160a08501520151910152565bf35b3461049c5760a036600319011261049c5760043560443561262360243561258c83610522565b6084359060643561259c836119c6565b6125a4613f6a565b6125ad8561494c565b916125b6612f19565b96875260208701526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408701526001600160a01b038516606087015261260461397b565b608087015260a086015260c08501523360e08501521515610100840152565b612658602073__$a48140799943db40fec4e369e92a011fa5$__936040518093819263f2b47e9d60e01b8352600483016139ce565b0381865af49081156107dd575f916126fb575b50156126e8575f5490823b1561049c576040516316aecce360e01b815260026004820152600660248201526005604482015260648101929092526001600160a01b03166084820152905f90829060a49082905af480156107dd576126d4575b505b610520613fc5565b80610a105f6126e293612ed9565b5f6126ca565b6126f691506115168161494c565b6126cc565b61271d915060203d602011612723575b6127158183612ed9565b8101906139b9565b5f61266b565b503d61270b565b3461049c57602036600319011261049c5760043561274781610522565b5f516020615eb75f395f51905f525460ff8160401c1690811561284a575b5061283b576127d99061279f600167ffffffffffffffff195f516020615eb75f395f51905f525416175f516020615eb75f395f51905f5255565b6801000000000000000068ff0000000000000000195f516020615eb75f395f51905f525416175f516020615eb75f395f51905f5255613ae9565b61280868ff0000000000000000195f516020615eb75f395f51905f5254165f516020615eb75f395f51905f5255565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290806020810161196d565b63f92ee8a960e01b5f5260045ffd5b6001915067ffffffffffffffff1610155f612765565b3461049c57602036600319011261049c57600161287e600435613cec565b015460405163e5c9274560e01b815260a082901c61ffff166004820152306024820152906020908290816001600160a01b038160448101610857565b3461049c575f6128c936610533565b6128d593929193613f6a565b6128e261057b3383613fea565b6128eb82613cec565b61290a836105ab846001600160a01b03165f52600660205260405f2090565b6020612988600161292c866001600160a01b03165f52600560205260405f2090565b94015461293f60d082901c60ff16615220565b6129546116ce6001600160a01b038316611697565b60405163a436458d60e01b815261ffff9091166004820152602481018a905233604482015297889283919082906064820190565b03925af19485156107dd575f95612ab7575b506129bb906106cb6129ab87614071565b82546001600160781b03166135a6565b826129e3610f1f8284906001918160071c5f5260205260fe60405f205491831b161c16151590565b612a40575b50506129f661079c826140a2565b6001600160a01b036040519116917fef18174796a5d2f91d51dc5e907a4d7867bbd6e800f6225168e0453d581d0dcd33928061077488888360209093929193604081019481520152565b612a9c91612a7f61ffff7f00000000000000000000000000000000000000000000000000000000000000001661ffff8114908115612aa3575b50613c20565b8160071c5f52602052600160fe60405f2092821b161b8154179055565b5f826129e8565b9050612ab05f5484615254565b105f612a79565b6129bb919550612ad59060203d6020116107d6576107c78183612ed9565b949061299a565b3461049c57602036600319011261049c576004356001600160c01b038116810361049c57610cce602091336152f2565b3461049c575f36600319011261049c57612b24613c36565b506060612b2f61397b565b612564604051809261ffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b3461049c575f36600319011261049c57602060405160018152f35b63ffffffff81160361049c57565b3461049c5760a036600319011261049c57602435600435612bb082612b82565b612bb936610e6b565b91612bc4363361441d565b612bd05f5483106131f2565b815f52600460205263ffffffff612bf88260405f209063ffffffff165f5260205260405f2090565b5460101c1615612c855761ffff8335612c108161343a565b1615612c765763ffffffff7f2d4f2760aaff0dfa53526a8fdd306864689a7d5e43f44ddfeece0f38315c298d91612c46856145aa565b612c608561111483611bb6885f52600460205260405f2090565b612c71604051928392169582613529565b0390a3005b6302f22cad60e61b5f5260045ffd5b6317e5b99760e01b5f5260045ffd5b3461049c57604036600319011261049c57610498612ceb602435600435612cba82612b82565b612cc2613c36565b50612ccc81613cec565b505f52600460205260405f209063ffffffff165f5260205260405f2090565b61ffff60405191612cfb83612ea1565b54818116835263ffffffff8160101c16602084015260301c16604082015260405191829182919091604061ffff81606084019582815116855263ffffffff6020820151166020860152015116910152565b3461049c57604036600319011261049c576001600160a01b036020610857602435612db76002612da9600435612d8185610522565b6105ab6001612d8f83613cec565b0154956001600160a01b03165f52600660205260405f2090565b01546001600160781b031690565b6040516360268b2760e11b815260a083901c61ffff1660048201526001600160781b03909116602482015293849283919082906044820190565b3461049c575f36600319011261049c5760206040517fba01f7bf3d3674c63670ec4a78b0d56aac1ad6e8c84468920b9e61bfe0b9851a8152f35b3461049c57602036600319011261049c57610520600435612e4b81610522565b613c54565b634e487b7160e01b5f52604160045260245ffd5b60e0810190811067ffffffffffffffff821117612e8057604052565b612e50565b60a0810190811067ffffffffffffffff821117612e8057604052565b6060810190811067ffffffffffffffff821117612e8057604052565b6020810190811067ffffffffffffffff821117612e8057604052565b90601f8019910116810190811067ffffffffffffffff821117612e8057604052565b6040519061130e60a083612ed9565b6040519061130e60e083612ed9565b6040519061130e61012083612ed9565b6040519061130e606083612ed9565b60405190612f4582612e85565b5f6080838281528260208201528260408201528260608201520152565b3561055381610522565b903590601e198136030182121561049c570180359067ffffffffffffffff821161049c57602001918160061b3603831361049c57565b634e487b7160e01b5f52603260045260245ffd5b9190811015612fc65760061b0190565b612fa2565b35610553816119c6565b929192803592612fe484610522565b6020820194612ffd612ff68785612f6c565b9050613d0f565b935f5b855181101561307c578061306b61302360019361301d8c8a612f6c565b90612fb6565b906020604051927f187dbd227227274b90655fb4011fc21dd749e8966fc040bd91e0b926092025655f526001600160a01b0381351682520135151560405260605f2091604052565b61307582896138ff565b5201613000565b5090919461312a939461308e86612f62565b906040516130b2816130a4602082018095613d41565b03601f198101835282612ed9565b519020916040870135918261312160608a0135956130a487604051948593602085019788909493926080926001600160a01b0360a08401977fba01f7bf3d3674c63670ec4a78b0d56aac1ad6e8c84468920b9e61bfe0b9851a8552166020840152604083015260608201520152565b51902090613d84565b5f5b6131368483612f6c565b9050811015613189578061318361315b61315660019461301d8988612f6c565b612f62565b61316485612f62565b61317d60206131778661301d8c8b612f6c565b01612fcb565b91613ef1565b0161312c565b50509050565b1561319657565b6282b42960e81b5f5260045ffd5b9081602091031261049c575190565b6040513d5f823e3d90fd5b634e487b7160e01b5f52601160045260245ffd5b906001600160781b03809116911603906001600160781b038211611d2057565b156131f957565b630b975aed60e21b5f5260045ffd5b1561320f57565b63e6c4247b60e01b5f5260045ffd5b1561322557565b6307d7e52d60e51b5f5260045ffd5b1561323b57565b631ce2603f60e31b5f5260045ffd5b5f198114611d205760010190565b919082604091031261049c576020825161327181610522565b9201516105538161091f565b1561328457565b63b77e1e0f60e01b5f5260045ffd5b1561329a57565b63e236476560e01b5f5260045ffd5b62ffffff81160361049c57565b35610553816132a9565b9061341a60c0600161130e946133036001600160a01b0386511682906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b019261333f6001600160a01b0360208301511685906001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19825416179055565b6040810151845460608301517fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff90911660a09290921b75ffff0000000000000000000000000000000000000000169190911760b09190911b76ff00000000000000000000000000000000000000000000161784556133e46133c6608083015162ffffff1690565b855462ffffff60b81b191660b89190911b62ffffff60b81b16178555565b61340f6133f560a083015160ff1690565b855460ff60d01b191660d09190911b60ff60d01b16178555565b015163ffffffff1690565b815463ffffffff60d81b191660d89190911b63ffffffff60d81b16179055565b61ffff81160361049c57565b9061ffff81356134558161343a565b16908254918061ffff19841617845567ffff000000000000604065ffffffff0000602085013561348481612b82565b60101b1693848465ffffffffffff1988161717875501356134a48161343a565b60301b169267ffffffffffffffff19161717179055565b91909160808060a083019462ffffff81356134d5816132a9565b16845260208101356134e6816119c6565b1515602085015260408101356134fb816119c6565b151560408501526060810135613510816119c6565b151560608501520135613522816119c6565b1515910152565b919091604061ffff8160608401958281356135438161343a565b16855263ffffffff602082013561355981612b82565b166020860152013561356a8161343a565b16910152565b6040519061357d82612e64565b5f60c0838281528260208201528260408201528260608201528260808201528260a08201520152565b906001600160781b03809116911601906001600160781b038211611d2057565b6001600160801b0381160361049c57565b67ffffffffffffffff81160361049c57565b6001600160801b0381356135fc816135c6565b166001600160801b0319600154161760015560208101359061361d826135d7565b7fffffffffffff00000000000000000000ffffffffffffffffffffffffffffffff79ffff000000000000000000000000000000000000000000000000604077ffffffffffffffff000000000000000000000000000000006001549560801b1693847fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff87161760015501356136b08161343a565b60c01b1692161717600155565b919091604061ffff8160608401956001600160801b0381356136de816135c6565b16855267ffffffffffffffff6020820135613559816135d7565b919082604091031261049c576020825192015190565b91908201809211611d2057565b61372481613cec565b926001600160a01b03811693845f52600560205260405f206137628482906001918160071c5f526020528160fe60405f205492821b16011c16151590565b1515851515146138455783859160ff600161379695015460d01c168361378b600183161561404e565b6137eb575b5061498a565b8183156137d8576137a6916149c6565b604051911515825233917f4763df430bc5274807f8ab4ce0734e7898513638418d6eec0c5285ef85f7f51f90602090a4565b50806115166137e6926140a2565b6137a6565b60026137f8911615614893565b61383261ffff7f00000000000000000000000000000000000000000000000000000000000000001661ffff81149081156138385750613c20565b5f613790565b9050612ab05f548461570a565b505050505050565b67ffffffffffffffff8111612e805760051b60200190565b9190811015612fc65760051b81013590601e198136030182121561049c57019081359167ffffffffffffffff831161049c57602001823603811361049c579190565b908092918237015f815290565b67ffffffffffffffff8111612e8057601f01601f191660200190565b3d156138fa573d906138e1826138b4565b916138ef6040519384612ed9565b82523d5f602084013e565b606090565b8051821015612fc65760209160051b010190565b60409061130e939594929561ffff60a0830197168252602082015201906040809180518452602081015160208501520151910152565b60409061130e939594929560a08201968252602082015201906040809180518452602081015160208501520151910152565b6040519061398882612ea1565b81604061ffff6001546001600160801b038116845267ffffffffffffffff8160801c16602085015260c01c16910152565b9081602091031261049c5751610553816119c6565b61130e909291926102806101006102a08301956002845260066020850152600560408501526004606085015280516080850152602081015160a08501526001600160a01b0360408201511660c0850152613a38606082015160e08601906001600160a01b03169052565b613a7460808201518386019061ffff604080926001600160801b03815116855267ffffffffffffffff6020820151166020860152015116910152565b60a08181015161016086015260c080830151805161018088015260208101516101a088015260408101516101c088015260608101516101e0880152608081015161020088015291820151610220870152015161024085015260e08101516001600160a01b031661026085015201511515910152565b613b8f9060405161ffff7f00000000000000000000000000000000000000000000000000000000000000001681527f6d87c7e547bc13244d61719fa011b6947b26036a16d69a607c1cf72a77d052bc60206001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692a2613b7a6001600160a01b0382161515613208565b613b82615af8565b613b8a615af8565b6147e7565b6001546001600160801b031615613ba257565b670de0b6b3a76400006001600160801b031960015416176001557f9062eec1933c38394d82dc926d7ddcd777a5cd08e1ae6baa94e90047338d345960405180613c1b81906060820191604061ffff6001546001600160801b038116845267ffffffffffffffff8160801c16602085015260c01c16910152565b0390a1565b15613c2757565b6301e09be360e31b5f5260045ffd5b60405190613c4382612ea1565b5f6040838281528260208201520152565b335f52600760205260ff613c7c8260405f20906001600160a01b03165f5260205260405f2090565b541615613ce957335f526007602052613ca98160405f20906001600160a01b03165f5260205260405f2090565b60ff1981541690556040515f81527f413bea992b9956f4f10f6c819bf7a6c8ed5baa119a2901fe221ae03171d5227760206001600160a01b0333941692a3565b50565b5f52600260205260405f206105536001600160a01b0360018301541615156131f2565b90613d198261384d565b613d266040519182612ed9565b8281528092613d37601f199161384d565b0190602036910137565b80516020909101905f5b818110613d585750505090565b8251845260209384019390920191600101613d4b565b15613d7557565b638baa579f60e01b5f5260045ffd5b93613e28929591613d9a613e2d95421115613d6e565b7f0000000000000000000000000000000000000000000000000000000000000000467f000000000000000000000000000000000000000000000000000000000000000014307f0000000000000000000000000000000000000000000000000000000000000000141615613e64575b6719010000000000005f52601a52603a5260426018205f603a5285615394565b613d6e565b613e3a8260401c826152f2565b809203613e45575050565b6001600160a01b03906301d4b62360e61b5f521660045260245260445ffd5b50613eec60a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f000000000000000000000000000000000000000000000000000000000000000060408201524660608201523060808201522090565b613e08565b60206001600160a01b03807f413bea992b9956f4f10f6c819bf7a6c8ed5baa119a2901fe221ae03171d52277939594951694855f5260078352613f5d85613f4c8360405f20906001600160a01b03165f5260205260405f2090565b9060ff801983541691151516179055565b60405194151585521692a3565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c613fb65760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b633ee5aeb560e01b5f5260045ffd5b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b906001600160a01b0316806001600160a01b03831614614047575f52600760205260405f209060ff600183015416918261402357505090565b60ff92509061404291906001600160a01b03165f5260205260405f2090565b541690565b5050600190565b1561405557565b6334dfd7c760e21b5f5260045ffd5b600161130e91161561404e565b6001600160781b03811161408b576001600160781b031690565b6306dfcc6560e41b5f52607860045260245260445ffd5b6140aa613570565b506001600160a01b036140be600183614dcf565b91167f837314749a8459031ad895d39a13552d1627fddc93d64b404bab0ae5f0798da75f80a2670de0b6b3a76400006040820151106140fa5790565b63851aedc160e01b5f5260045ffd5b91602061130e9294936080810195815201906040809180518452602081015160208501520151910152565b61130e9092919260608101936040809180518452602081015160208501520151910152565b919091614177816001600160a01b03165f52600560205260405f2090565b831580614341575b613189576141a661418f85615448565b600183019062ffffff1662ffffff19825416179055565b6141b25f545b82615471565b5f198114614303576141d9816105ab856001600160a01b03165f52600660205260405f2090565b9160016141ee835f52600260205260405f2090565b01546142076116976116a360a084901c61ffff166105ef565b6040516316be8c1960e31b815260048101839052909190602081602481865afa9081156107dd57614242918a915f916142e5575b5087614b1f565b91803b1561049c57825f9161426e938360405180968195829463341f7dcf60e01b845260048401614109565b03925af180156107dd576141b29561428d9284926142d1575b50614caf565b827f4fd0c5440d5b8c1dd712c65f039f54384c59e81a139427b0a9155260d974a9a7604051806142c76001600160a01b038a169582614134565b0390a391906141ac565b80610a105f6142df93612ed9565b5f614287565b6142fd915060203d81116107d6576107c78183612ed9565b5f61423b565b505060405192835290916001600160a01b03909116907f9a9082fd74a00ac52b567642a2d8fd3383cb2bd8690f6b2a3b7b37aaf489dac190602090a2565b5062ffffff614356600183015462ffffff1690565b161561417f565b90825f52600260205261ffff600160405f20015460a01c1614918261438157505090565b9091505f5260026020526001600160a01b0380600160405f2001541691161490565b9060041161049c5790600490565b356001600160e01b03198116929190600482106143cc575050565b6001600160e01b031960049290920360031b82901b16169150565b91926060936001600160a01b03829316845260406020850152816040850152848401375f828201840152601f01601f1916010190565b61445a61443e5f516020615e975f395f51905f52546001600160a01b031690565b61445161444b855f6143a3565b906143b1565b90833091615639565b901561446557505050565b63ffffffff1615614550576144b17401000000000000000000000000000000000000000060ff60a01b195f516020615e975f395f51905f525416175f516020615e975f395f51905f5255565b6144d56116976116975f516020615e975f395f51905f52546001600160a01b031690565b91823b1561049c57614502925f80809460405196879586948593634a63ebf760e11b8552600485016143e7565b03925af180156107dd5761453c575b5061130e60ff60a01b195f516020615e975f395f51905f5254165f516020615e975f395f51905f5255565b80610a105f61454a93612ed9565b5f614511565b62d1953b60e31b5f526001600160a01b031660045260245ffd5b62ffffff620186a0913561457d816132a9565b161161458557565b63c0534e9560e01b5f5260045ffd5b1561459b57565b6302ca6a8b60e31b5f5260045ffd5b80356145b58161343a565b61ffff811661271081109182614634575b82614600575b5050156145f1576127106145ea604061130e9301356105ef8161343a565b1115614594565b63cf8e83b160e01b5f5260045ffd5b61271092509063ffffffff61462c9261462660208701359161462183612b82565b61343a565b166156ac565b105f806145cc565b915061271063ffffffff602085013561464c81612b82565b161015916145c6565b906001600160a01b03169061466b821515613208565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803b1561049c575f8091604460405180948193636d4c247960e01b83528760048401528860248401525af180156107dd576146f2575b507f18a45d070f507b6387b78837652d7468e733927acc7f9a13d9cc308675735c085f80a3565b806146fe5f8093612ed9565b80031261049c575f6146cb565b61ffff811161471b5761ffff1690565b6306dfcc6560e41b5f52601060045260245260445ffd5b60ff939291901561477a576001905b1561477157600217905b1561476857600417905b15614761576008171690565b60f7161690565b60fb1690614755565b60fd169061474b565b5f90614741565b9060209060246001600160a01b039460405195869384926316be8c1960e31b84526004840152165afa9081156107dd576147c2925f926147c6575b506156ca565b9091565b6147e091925060203d6020116107d6576107c78183612ed9565b905f6147bc565b60206001600160a01b037f2f658b440c35314f52658ea8a740e05b284cdc84dc9ae01e891f21b8933e7cad92168073ffffffffffffffffffffffffffffffffffffffff195f516020615e975f395f51905f525416175f516020615e975f395f51905f5255604051908152a1565b60409081516148638382612ed9565b600581526453706f6b6560d81b60208201529161488281519182612ed9565b60018152603160f81b602082015290565b1561489a57565b636d30581560e01b5f5260045ffd5b600261130e916148bc600182161561404e565b1615614893565b9290916001600160a01b039081604051946323b872dd60e01b5f52166004521660245260445260205f60648180865af160015f511481161561492d575b6040919091525f606052156149125750565b635274afe760e01b5f526001600160a01b031660045260245ffd5b6001811516614943573d15833b15151616614900565b503d5f823e3d90fd5b5f61055391614959613570565b50614dcf565b63ffffffff81116149735763ffffffff1690565b6306dfcc6560e41b5f52602060045260245260445ffd5b9060018060fe83821b16011b925f146149b15760071c5f5260205260405f20908154179055565b60071c5f5260205260405f2090198154169055565b9060207f5790b5f096c9cfee6b98a4e2d4f54ff3fc4ca306df5bc2093d93a36496d917b891805f5260028252614a486001600160a01b0363ffffffff600160405f20015460d81c16951694855f526006845260405f20835f528452600260405f20019063ffffffff60781b82549160781b169063ffffffff60781b1916179055565b604051908152a2565b90614a5e919392936156ca565b92906b033b2e3c9fd0803ce800000080850490850615150190818101808211611d2057831015614abc5750808210614a9d578103908111611d20579190565b506b033b2e3c9fd0803ce8000000808202935083040361049c575f9190565b9150509190565b744f3a68dbc8f03f243baf513267aa9a3ee524f8e028811182151761049c576b033b2e3c9fd0803ce8000000020490565b81810292918115918404141715611d2057565b81810392915f138015828513169184121617611d2057565b614b27613c36565b5080548060781c6001600160781b0316916001015460180b9384614b4b8585614af4565b614b5490615c2a565b90614b5e91614b07565b614b6790615c66565b916001600160781b031690614b7b916156ac565b92614b869084614af4565b614b8f90615c2a565b90614b9990615c2a565b614ba291614b07565b91614bac90615c2a565b90614bb690615c2a565b614bbf91614b07565b91614bc991614b07565b60405191614bd8606084612ed9565b825260208201525f604082015290565b919392614bf3613c36565b5082549060016001600160781b038360781c1694015460180b926001600160781b03614c38614c3386614c2e614c298c8b614af4565b615c2a565b614b07565b615c66565b9316908103908111611d2057614c5891614c51916156ac565b9586614af4565b92848203918211611d2057614c85614c7f614c8b614c9194614c85614c7f614c9799615c2a565b91615c2a565b90614b07565b97615c2a565b93614b07565b614c9f612f29565b9283526020830152604082015290565b60019092919280547fffff000000000000000000000000000000ffffffffffffffffffffffffffffff7dffffffffffffffffffffffffffffff000000000000000000000000000000614d16614d1188516001600160781b038660781c166157a1565b614071565b60781b169116178155016020815460180b930151925f8482019485129112908015821691151617611d20578260180b90838203614d995761130e929350907fffffffffffffff000000000000000000000000000000000000000000000000008254169078ffffffffffffffffffffffffffffffffffffffffffffffffff16179055565b8363327269a760e01b5f5260c860045260245260445ffd5b8115614dbb570490565b634e487b7160e01b5f52601260045260245ffd5b614dd7613570565b91614df3826001600160a01b03165f52600560205260405f2090565b5f5494614e08614e03878461570a565b6157cd565b91614e3e6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016975b82615816565b90929082905f19821461511657614e6a826105ab8b6001600160a01b03165f52600660205260405f2090565b90614e7d835f52600260205260405f2090565b60405163d45c35ff60e01b8152600481018590529092906020818f81806024810103915afa9384156107dd578b915f956150f3575b506001018054909560ff60b083901c1694614f57575b505050614e3e96614edf575b505050509190614e38565b614f12614f2d91614f329554614f0c6105ef614f01836001600160a01b031690565b9260a01c61ffff1690565b916159e8565b6020614f248251604084015190614af4565b9101519061370e565b61595f565b614f4160808a0191825161370e565b905260c08801600181510190525f808080614ed4565b614fbd926105ef92614f74614fb5935f52600460205260405f2090565b91156150de5760d81c63ffffffff1660028601805472ffffffff0000000000000000000000000000001916607883901b63ffffffff60781b16179055610d6e565b5461ffff1690565b9687614fcd575b96808b91614ec8565b614ff0614fe460028401546001600160781b031690565b6001600160781b031690565b80614ffc575b50614fc4565b61504a6020875492615017611697856001600160a01b031690565b6040516360268b2760e11b815261ffff60a087901c16600482015260248101929092529092839190829081906044820190565b03915afa80156107dd578f916150a88e614e3e9d6150a361507a8c8c6150b2986020985f916150c1575b5061595f565b80936060890161508b83825161370e565b905260a089018051909a60b81c62ffffff1691615984565b614af4565b920191825161370e565b9052600181510190525f614ff6565b6150d89150893d81116107d6576107c78183612ed9565b5f615074565b50600285015460781c63ffffffff1690611bb6565b600191955061510f9060203d81116107d6576107c78183612ed9565b9490614eb2565b505050505093945091505060808301805115155f146152145761514761513f6020860151615a7e565b825190615a99565b60408501525b6060840151806151f5575b5061516282615ab9565b516b033b2e3c9fd0803ce800000080820491061515019081925f925b8251518410156151ea5780156151c4576151b26001916151b96151a18787615ad2565b808418908411028318939084614af4565b895161370e565b88520393019261517e565b9250939290505b8082106151d757505090565b6151e5918351910390615ae6565b815290565b9250939290506151cb565b61520c60208601916152078351615a7e565b614db1565b90525f615158565b5f19604085015261514d565b600490615230600182161561404e565b61523d6002821615614893565b161561524557565b6355621e4960e11b5f5260045ffd5b6152a0916152a58160071c938492835f528460205260405f20549060fe7f55555555555555555555555555555555555555555555555555555555555555559160011b16610100031c1690565b615b23565b925b6152b057505090565b5f19018092815f52826020526152eb7f555555555555555555555555555555555555555555555555555555555555555560405f205416615b23565b01926152a7565b906001600160a01b0361055392165f527f474d4a5585c1bae3dbeb574bb96408c7174aadd8ab635de4ab498e2723195f006020526153448160405f20906001600160c01b03165f5260205260405f2090565b805467ffffffffffffffff19808216600167ffffffffffffffff9384169081019093161790925560409290921b161790565b6004111561538057565b634e487b7160e01b5f52602160045260245ffd5b929190833b6153d157906153a89291615bcc565b506153b281615376565b1591826153be57505090565b6001600160a01b03919250811691161490565b6153dd839492946138b4565b936153eb6040519586612ed9565b838552368482011161049c57845f602086829760649583809b01378301015280519060405193630b135d3f60e11b855260048501526040602485015286820190604485015e01915afa630b135d3f60e11b5f5114601f3d11161690565b62ffffff811161545a5762ffffff1690565b6306dfcc6560e41b5f52601860045260245260445ffd5b91906155406154bc8260071c92835f528560205260405f20549060fe7f55555555555555555555555555555555555555555555555555555555555555559160011b16610100031c1690565b7f07060605060205040602030205040301060502050303040105050304000000006f8421084210842108cc6318c6db6d54be826001600160801b031060071b831560081b1783811c67ffffffffffffffff1060061b1783811c63ffffffff1060051b1783811c61ffff1060041b1783811c60ff1060031b1792831c1c601f161a1790565b610100811480615630575b1561561257505f190190815f528260205261560a7f555555555555555555555555555555555555555555555555555555555555555560405f2054167f07060605060205040602030205040301060502050303040105050304000000006f8421084210842108cc6318c6db6d54be826001600160801b031060071b831560081b1783811c67ffffffffffffffff1060061b1783811c63ffffffff1060051b1783811c61ffff1060041b1783811c60ff1060031b1792831c1c601f161a1790565b919091615540565b91925061010082036156255750505f1990565b60071b9060011c0190565b5081151561554b565b5f90604092959395829683966001600160a01b0386519281602085019563b700961360e01b875216602485015216604483015263ffffffff60e01b16606482015260648152615689608482612ed9565b8380528360205251915afa61569a57565b9150505f51906020518060201c150290565b815f19048111158215171561049c5702612710808206151591040190565b91906001600160781b036156de8285615c00565b935416815f19048111158215171561049c57026b033b2e3c9fd0803ce800000080820615159104019190565b615754918060071c928391825f52836020527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60fe60405f20549260011b16610100031c16615b23565b925b61575f57505090565b5f19018092815f528260205261579a7faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa60405f205416615b23565b0192615756565b905f8112156157c157600160ff1b8114611d20578101908111611d205790565b8101809111611d205790565b60606040516157db81612ebd565b526157e58161384d565b906157f36040519283612ed9565b808252615802601f199161384d565b01366020830137604051906151e582612ebd565b91908060071c9061584b6154bc6158358487905f5260205260405f2090565b5492839060fe5f199160011b16610100031c1690565b905b610100821480615956575b156159075750505f1901906158758284905f5260205260405f2090565b546158fe817f07060605060205040602030205040301060502050303040105050304000000006f8421084210842108cc6318c6db6d54be826001600160801b031060071b831560081b1783811c67ffffffffffffffff1060061b1783811c63ffffffff1060051b1783811c61ffff1060041b1783811c60ff1060031b1792831c1c601f161a1790565b9092919261584d565b9293509190610100830361592157505f19925f9250829150565b615946916159386159328560011c90565b60011b90565b1c929060071b9060011c0190565b9160026001831615159216151590565b50821515615858565b9161596a9192614af4565b906012039060128211611d205761055391600a0a90614af4565b9263ffffffff92838110806159c3575b156159b4578303928311611d20576159b19260e01b1792516138ff565b52565b631248a47160e11b5f5260045ffd5b507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8210615994565b916001600160a01b039160246020926159ff613c36565b5060405194859384926316be8c1960e31b84526004840152165afa9081156107dd575f91615a5f575b50615a3e816001600160781b0384541693615c00565b6001600160781b03615a4e612f29565b931683526020830152604082015290565b615a78915060203d6020116107d6576107c78183612ed9565b5f615a28565b90655af3107a4000820291655af3107a400083040361049c57565b906b033b2e3c9fd0803ce8000000615ab092615c82565b6105535f615376565b600261130e9151602080825160051b8301019101615ded565b6147c291602091519060051b010151615d0d565b90801561049c57808206151591040190565b60ff5f516020615eb75f395f51905f525460401c1615615b1457565b631afcd79f60e31b5f5260045ffd5b7f01010101010101010101010101010101010101010101010101010101010101017f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f55555555555555555555555555555555555555555555555555555555555555558360011c1683037f3333333333333333333333333333333333333333333333333333333333333333808260021c169116018060041c01160260f81c905f191460081b1790565b9060418303615bf657615bef9250602081013591604082359201355f1a90615d48565b9192909190565b50505f9160029190565b614c3390614c2e614c296105539460016001600160781b03855460781c1694015460180b93614af4565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111615c545790565b63123baf0360e11b5f5260045260245ffd5b5f8112615c705790565b635467221960e11b5f5260045260245ffd5b91615c8d8284615dca565b9290938415615d005784831115615cf35790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b6011600384150218615ddd565b5050906105539250614db1565b908115615d41577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff63ffffffff8360e01c9003921690565b5f91508190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411615dbf579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156107dd575f516001600160a01b03811615615db557905f905f90565b505f906001905f90565b5050505f9160039190565b905f198183099102908180821091030391565b634e487b715f526020526024601cfd5b9190604083820310615e5f5782519282818095602084015b858110615e2b57505082615e1f9351825182528252615ded565b602061130e9301615ded565b91509150615e3b82825187615e64565b615e4c575b60200184918691615e05565b6020909501805186518252865294615e40565b505050565b80600114615e8b57600214615e8757634e487b7160e01b5f52605160045260245ffd5b1190565b509061055391614dcf56fef3177357ab46d8af007ab3fdb9af81da189e1068fefdc0073dca88a2cab40a00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a164736f6c634300081c000af0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00 \ No newline at end of file diff --git a/tests/unit/scripts/GenerateBytecode.t.sol b/tests/unit/scripts/GenerateBytecode.t.sol new file mode 100644 index 000000000..8973ed7e1 --- /dev/null +++ b/tests/unit/scripts/GenerateBytecode.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Test} from 'forge-std/Test.sol'; + +import {BytecodeLoader} from 'tests/utils/BytecodeLoader.sol'; + +contract GenerateBytecodeScript is Test { + string private constant HUB_BYTECODE_PATH = 'tests/bin/hub.bytecode'; + string private constant SPOKE_INSTANCE_BYTECODE_PATH = 'tests/bin/spokeInstance.bytecode'; + + function test_generated_HubBytecode() public view { + bytes memory hubBytecode = vm.getCode('src/hub/Hub.sol:Hub'); + + assertEq( + hubBytecode, + BytecodeLoader.loadHubBytecode(), + 'Loaded Hub bytecode does not match generated bytecode' + ); + } + + function test_generated_SpokeInstanceBytecode() public view { + bytes memory spokeInstanceBytecode = vm.getCode( + 'src/spoke/instances/SpokeInstance.sol:SpokeInstance' + ); + + assertEq( + spokeInstanceBytecode, + BytecodeLoader.loadSpokeInstanceBytecode(), + 'Loaded SpokeInstance bytecode does not match generated bytecode' + ); + } +} diff --git a/tests/utils/BytecodeLoader.sol b/tests/utils/BytecodeLoader.sol new file mode 100644 index 000000000..bca637cbd --- /dev/null +++ b/tests/utils/BytecodeLoader.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {Vm} from 'forge-std/Vm.sol'; + +import {LiquidationLogic} from 'src/spoke/libraries/LiquidationLogic.sol'; + +library BytecodeLoader { + Vm private constant vm = Vm(address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))); + + string private constant HUB_BYTECODE_PATH = 'tests/bin/hub.bytecode'; + string private constant SPOKE_INSTANCE_BYTECODE_PATH = 'tests/bin/spokeInstance.bytecode'; + + string private constant LIQUIDATION_LOGIC_PLACEHOLDER = + '__$a48140799943db40fec4e369e92a011fa5$__'; + + function loadHubBytecode() public view returns (bytes memory) { + return vm.readFileBinary(HUB_BYTECODE_PATH); + } + + function loadSpokeInstanceBytecode() public view returns (bytes memory) { + string memory hexBytecode = vm.readFile(SPOKE_INSTANCE_BYTECODE_PATH); + string memory addrHex = vm.replace( + vm.toString(abi.encodePacked(address(LiquidationLogic))), + '0x', + '' + ); + string memory linked = vm.replace(hexBytecode, LIQUIDATION_LOGIC_PLACEHOLDER, addrHex); + return vm.parseBytes(linked); + } +} diff --git a/tests/utils/DeployHub.sol b/tests/utils/DeployHub.sol new file mode 100644 index 000000000..1e73bec93 --- /dev/null +++ b/tests/utils/DeployHub.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {BytecodeLoader} from 'tests/utils/BytecodeLoader.sol'; + +import {Create2Utils} from 'tests/Create2Utils.sol'; + +/// @notice Helper to deploy Hub from custom profile precompiled bytecode +contract DeployHub { + /// @notice Deploys a Hub contract using CREATE2 and the stored bytecode with the provided deployment arguments. + /// @param deployArgs The constructor arguments for the Hub contract, encoded as bytes. + /// @param salt The salt to use for the CREATE2 deployment, allowing for deterministic address generation. + /// @return The address of the deployed Hub contract. + function deployHub(bytes memory deployArgs, bytes32 salt) public returns (address) { + Create2Utils.loadCreate2Factory(); + + bytes memory bytecode = BytecodeLoader.loadHubBytecode(); + + return Create2Utils.create2Deploy(salt, abi.encodePacked(bytecode, deployArgs)); + } +} diff --git a/tests/utils/DeploySpoke.sol b/tests/utils/DeploySpoke.sol new file mode 100644 index 000000000..a8a52826a --- /dev/null +++ b/tests/utils/DeploySpoke.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (c) 2025 Aave Labs +pragma solidity ^0.8.0; + +import {BytecodeLoader} from 'tests/utils/BytecodeLoader.sol'; + +import {Create2Utils} from 'tests/Create2Utils.sol'; +import {DeployUtils} from 'tests/DeployUtils.sol'; + +/// @notice Helper to deploy Spoke from custom profile precompiled bytecode +contract DeploySpoke { + /// @notice Deploys a proxified SpokeInstance contract using CREATE2 and the stored bytecode with the provided deployment arguments, and proxified using initialize arguments. + /// @param deployArgs The constructor arguments for the SpokeInstance implementation contract, encoded as bytes. + /// @param initArgs The initialization arguments for the TransparentUpgradeableProxy, encoded as bytes. + /// @param salt The salt to use for the CREATE2 deployment, allowing for deterministic address generation. + /// @return The address of the deployed SpokeInstance implementation + /// @return The address of the deployed SpokeInstance proxy + function deploySpoke( + bytes memory deployArgs, + bytes memory initArgs, + bytes32 salt + ) public returns (address, address) { + Create2Utils.loadCreate2Factory(); + + bytes memory bytecode = BytecodeLoader.loadSpokeInstanceBytecode(); + + address impl = Create2Utils.create2Deploy(salt, abi.encodePacked(bytecode, deployArgs)); + address proxy = DeployUtils.proxify(impl, msg.sender, initArgs); + + return (impl, proxy); + } +} From bec36f3eaab6c04c2760f2dc59509d0a51d42731 Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:14:14 +0100 Subject: [PATCH 2/6] fix : add generate step in CIs --- .github/actions/generate-bytecode/action.yaml | 9 +++++++++ .github/workflows/tests-merge.yml | 3 +++ .github/workflows/tests-pr.yml | 3 +++ 3 files changed, 15 insertions(+) create mode 100644 .github/actions/generate-bytecode/action.yaml diff --git a/.github/actions/generate-bytecode/action.yaml b/.github/actions/generate-bytecode/action.yaml new file mode 100644 index 000000000..20a367891 --- /dev/null +++ b/.github/actions/generate-bytecode/action.yaml @@ -0,0 +1,9 @@ +name: "Generate bytecode binaries" +description: "Generate Hub and SpokeInstance bytecode binaries" + +runs: + using: "composite" + steps: + - name: Generate + shell: bash + run: forge script scripts/utils/GenerateBytecodeScript.s.sol diff --git a/.github/workflows/tests-merge.yml b/.github/workflows/tests-merge.yml index 602020e6b..af64791e3 100644 --- a/.github/workflows/tests-merge.yml +++ b/.github/workflows/tests-merge.yml @@ -27,6 +27,9 @@ jobs: - name: Run Forge size uses: bgd-labs/github-workflows/.github/actions/foundry-size@main + - name: Run Generate bytecode + uses: aave/aave-v4/.github/actions/foundry-size@main + - name: Run Forge tests id: test uses: bgd-labs/github-workflows/.github/actions/foundry-test@main diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index 95efca663..16120baf8 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -24,6 +24,9 @@ jobs: - name: Run Forge size uses: bgd-labs/github-workflows/.github/actions/foundry-size@main + - name: Run Generate bytecode + uses: aave/aave-v4/.github/actions/foundry-size@main + - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main From bfba762a1e65ee9d3672e5ac1afa89621009f20e Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:15:25 +0100 Subject: [PATCH 3/6] fix : fix CI --- .github/workflows/tests-merge.yml | 2 +- .github/workflows/tests-pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests-merge.yml b/.github/workflows/tests-merge.yml index af64791e3..9b9095c81 100644 --- a/.github/workflows/tests-merge.yml +++ b/.github/workflows/tests-merge.yml @@ -28,7 +28,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/foundry-size@main + uses: aave/aave-v4/.github/actions/generate-bytecode@main - name: Run Forge tests id: test diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index 16120baf8..ca099f4b6 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -25,7 +25,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/foundry-size@main + uses: aave/aave-v4/.github/actions/generate-bytecode@main - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main From 059020027c6832dc0fe4f135ac91ca8d4ba509d9 Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:16:44 +0100 Subject: [PATCH 4/6] fix : fix CI --- .github/workflows/tests-merge.yml | 2 +- .github/workflows/tests-pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests-merge.yml b/.github/workflows/tests-merge.yml index 9b9095c81..50df4bf99 100644 --- a/.github/workflows/tests-merge.yml +++ b/.github/workflows/tests-merge.yml @@ -28,7 +28,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/generate-bytecode@main + uses: aave/aave-v4/.github/actions/generate-bytecode - name: Run Forge tests id: test diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index ca099f4b6..9aa2cf8e5 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -25,7 +25,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/generate-bytecode@main + uses: aave/aave-v4/.github/actions/generate-bytecode - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main From 69684cd53d4c810090c322a463c7694f1620f44b Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:20:57 +0100 Subject: [PATCH 5/6] fix : fix CI --- .github/workflows/tests-merge.yml | 2 +- .github/workflows/tests-pr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests-merge.yml b/.github/workflows/tests-merge.yml index 50df4bf99..5319cb1d8 100644 --- a/.github/workflows/tests-merge.yml +++ b/.github/workflows/tests-merge.yml @@ -28,7 +28,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/generate-bytecode + uses: ./.github/actions/generate-bytecode - name: Run Forge tests id: test diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index 9aa2cf8e5..d4b9d7901 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -25,7 +25,7 @@ jobs: uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - name: Run Generate bytecode - uses: aave/aave-v4/.github/actions/generate-bytecode + uses: ./.github/actions/generate-bytecode - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main From b2b6313b686d38f2c0d58acae0fb88b2256ec46d Mon Sep 17 00:00:00 2001 From: Kogaroshi <25688223+Kogaroshi@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:41:38 +0100 Subject: [PATCH 6/6] fix : remove new CI action --- .github/actions/generate-bytecode/action.yaml | 9 --------- .github/workflows/tests-merge.yml | 3 --- .github/workflows/tests-pr.yml | 3 --- 3 files changed, 15 deletions(-) delete mode 100644 .github/actions/generate-bytecode/action.yaml diff --git a/.github/actions/generate-bytecode/action.yaml b/.github/actions/generate-bytecode/action.yaml deleted file mode 100644 index 20a367891..000000000 --- a/.github/actions/generate-bytecode/action.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: "Generate bytecode binaries" -description: "Generate Hub and SpokeInstance bytecode binaries" - -runs: - using: "composite" - steps: - - name: Generate - shell: bash - run: forge script scripts/utils/GenerateBytecodeScript.s.sol diff --git a/.github/workflows/tests-merge.yml b/.github/workflows/tests-merge.yml index 5319cb1d8..602020e6b 100644 --- a/.github/workflows/tests-merge.yml +++ b/.github/workflows/tests-merge.yml @@ -27,9 +27,6 @@ jobs: - name: Run Forge size uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - - name: Run Generate bytecode - uses: ./.github/actions/generate-bytecode - - name: Run Forge tests id: test uses: bgd-labs/github-workflows/.github/actions/foundry-test@main diff --git a/.github/workflows/tests-pr.yml b/.github/workflows/tests-pr.yml index d4b9d7901..95efca663 100644 --- a/.github/workflows/tests-pr.yml +++ b/.github/workflows/tests-pr.yml @@ -24,9 +24,6 @@ jobs: - name: Run Forge size uses: bgd-labs/github-workflows/.github/actions/foundry-size@main - - name: Run Generate bytecode - uses: ./.github/actions/generate-bytecode - - name: Run Gas report uses: bgd-labs/github-workflows/.github/actions/foundry-gas-report@main