From ccc1890e268307ad6e2d4d9508fc7f09fceabc23 Mon Sep 17 00:00:00 2001 From: Moody Salem Date: Thu, 9 Jan 2025 10:12:07 -0500 Subject: [PATCH] add the l1 proxy code --- .github/workflows/test.yaml | 43 +++++++- .gitmodules | 3 + l1_proxy/.gitignore | 19 ++++ .../Deploy.s.sol/1/run-1736266757.json | 49 ++++++++++ .../broadcast/Deploy.s.sol/1/run-latest.json | 49 ++++++++++ .../Deploy.s.sol/11155111/run-1736266524.json | 49 ++++++++++ .../Deploy.s.sol/11155111/run-latest.json | 49 ++++++++++ l1_proxy/foundry.toml | 6 ++ l1_proxy/lib/forge-std | 1 + l1_proxy/script/Deploy.s.sol | 37 +++++++ l1_proxy/src/StarknetOwnerProxy.sol | 57 +++++++++++ l1_proxy/test/StarknetOwnerProxy.t.sol | 98 +++++++++++++++++++ 12 files changed, 458 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 100644 l1_proxy/.gitignore create mode 100644 l1_proxy/broadcast/Deploy.s.sol/1/run-1736266757.json create mode 100644 l1_proxy/broadcast/Deploy.s.sol/1/run-latest.json create mode 100644 l1_proxy/broadcast/Deploy.s.sol/11155111/run-1736266524.json create mode 100644 l1_proxy/broadcast/Deploy.s.sol/11155111/run-latest.json create mode 100644 l1_proxy/foundry.toml create mode 160000 l1_proxy/lib/forge-std create mode 100644 l1_proxy/script/Deploy.s.sol create mode 100644 l1_proxy/src/StarknetOwnerProxy.sol create mode 100644 l1_proxy/test/StarknetOwnerProxy.t.sol diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7245575..d212949 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,9 +7,13 @@ on: pull_request: branches: - main + workflow_dispatch: + +env: + FOUNDRY_PROFILE: ci jobs: - main: + cairo: runs-on: ubuntu-latest steps: - name: Checkout @@ -20,4 +24,39 @@ jobs: - name: Test the code run: | - scarb test \ No newline at end of file + scarb test + + solidity: + strategy: + fail-fast: true + + name: Foundry project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Show Forge version + run: | + forge --version + + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + + - name: Run Forge build + run: | + forge build --sizes + id: build + + - name: Run Forge tests + run: | + forge test -vvv + id: test diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..572c8db --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "l1_proxy/lib/forge-std"] + path = l1_proxy/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/l1_proxy/.gitignore b/l1_proxy/.gitignore new file mode 100644 index 0000000..a25b8ce --- /dev/null +++ b/l1_proxy/.gitignore @@ -0,0 +1,19 @@ +.vscode +.codegpt + +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env + +.codegpt \ No newline at end of file diff --git a/l1_proxy/broadcast/Deploy.s.sol/1/run-1736266757.json b/l1_proxy/broadcast/Deploy.s.sol/1/run-1736266757.json new file mode 100644 index 0000000..4920b74 --- /dev/null +++ b/l1_proxy/broadcast/Deploy.s.sol/1/run-1736266757.json @@ -0,0 +1,49 @@ +{ + "transactions": [ + { + "hash": "0x58d886795afd7ff428175030088865eb35fbe30eae5e963c32a39246904a721f", + "transactionType": "CREATE", + "contractName": "StarknetOwnerProxy", + "contractAddress": "0xd2f72213a2d1f9d95f10bf4afe2ba8a2fb4868f2", + "function": null, + "arguments": [ + "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4", + "2354502934501836923955011505963489193673442986857363336683304411560511969997" + ], + "transaction": { + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "gas": "0x79996", + "value": "0x0", + "input": "0x60c060405234801561000f575f5ffd5b5060405161069638038061069683398101604081905261002e91610044565b6001600160a01b0390911660805260a05261007b565b5f5f60408385031215610055575f5ffd5b82516001600160a01b038116811461006b575f5ffd5b6020939093015192949293505050565b60805160a0516105ed6100a95f395f818161010901526102d001525f8181609201526102a101526105ed5ff3fe608060405260043610610041575f3560e01c80635add2f701461004c5780637fab394d14610081578063b61d27f6146100cc578063f003a0c5146100f8575f5ffd5b3661004857005b5f5ffd5b348015610057575f5ffd5b5061006b6100663660046103ed565b610139565b60405161007891906104b7565b60405180910390f35b34801561008c575f5ffd5b506100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610078565b3480156100d7575f5ffd5b506100eb6100e63660046103ed565b610240565b60405161007891906104d0565b348015610103575f5ffd5b5061012b7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610078565b60605f601f61014984601e610505565b610153919061052a565b90505f610161826003610505565b67ffffffffffffffff81111561017957610179610549565b6040519080825280602002602001820160405280156101a2578160200160208202803683370190505b509050866001600160a01b0316815f815181106101c1576101c161055d565b60200260200101818152505085816001815181106101e1576101e161055d565b60200260200101818152505084849050816002815181106102045761020461055d565b60209081029190910101525f5b8281101561023557601f810286013560081c60048201602002830152600101610211565b509695505050505050565b60606001600160a01b038516158061026057506001600160a01b03851630145b1561027e5760405163416aebb560e11b815260040160405180910390fd5b8347101561029f57604051631e9acf1760e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c9dd5c07f00000000000000000000000000000000000000000000000000000000000000006102fb88888888610139565b6040518363ffffffff1660e01b8152600401610318929190610571565b6020604051808303815f875af1158015610334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103589190610591565b505f5f866001600160a01b03168686866040516103769291906105a8565b5f6040518083038185875af1925050503d805f81146103b0576040519150601f19603f3d011682016040523d82523d5f602084013e6103b5565b606091505b5091509150816103e3578060405163a5fa8d2b60e01b81526004016103da91906104d0565b60405180910390fd5b9695505050505050565b5f5f5f5f60608587031215610400575f5ffd5b84356001600160a01b0381168114610416575f5ffd5b935060208501359250604085013567ffffffffffffffff811115610438575f5ffd5b8501601f81018713610448575f5ffd5b803567ffffffffffffffff81111561045e575f5ffd5b87602082840101111561046f575f5ffd5b949793965060200194505050565b5f8151808452602084019350602083015f5b828110156104ad57815186526020958601959091019060010161048f565b5093949350505050565b602081525f6104c9602083018461047d565b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082018082111561052457634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8261054457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f610589604083018461047d565b949350505050565b5f602082840312156105a1575f5ffd5b5051919050565b818382375f910190815291905056fea26469706673582212208e39481fc28d11c7a6da7706c50f24f8b563dca7188a2df30970b65ec546b9ac64736f6c634300081c0033000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c4053499f7aa2706395060fe72d00388803fb2dcc111429891ad7b2d9dcea29acd", + "nonce": "0x235", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x9666a8", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x58d886795afd7ff428175030088865eb35fbe30eae5e963c32a39246904a721f", + "transactionIndex": "0x6e", + "blockHash": "0x39d47bd69be96c71a6b498346659f3099234e962279466f55339fbe2be7772f0", + "blockNumber": "0x149306d", + "gasUsed": "0x5d89b", + "effectiveGasPrice": "0x57a2bad5f", + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "to": null, + "contractAddress": "0xd2f72213a2d1f9d95f10bf4afe2ba8a2fb4868f2" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736266757, + "chain": 1, + "commit": "27ce525" +} \ No newline at end of file diff --git a/l1_proxy/broadcast/Deploy.s.sol/1/run-latest.json b/l1_proxy/broadcast/Deploy.s.sol/1/run-latest.json new file mode 100644 index 0000000..4920b74 --- /dev/null +++ b/l1_proxy/broadcast/Deploy.s.sol/1/run-latest.json @@ -0,0 +1,49 @@ +{ + "transactions": [ + { + "hash": "0x58d886795afd7ff428175030088865eb35fbe30eae5e963c32a39246904a721f", + "transactionType": "CREATE", + "contractName": "StarknetOwnerProxy", + "contractAddress": "0xd2f72213a2d1f9d95f10bf4afe2ba8a2fb4868f2", + "function": null, + "arguments": [ + "0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4", + "2354502934501836923955011505963489193673442986857363336683304411560511969997" + ], + "transaction": { + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "gas": "0x79996", + "value": "0x0", + "input": "0x60c060405234801561000f575f5ffd5b5060405161069638038061069683398101604081905261002e91610044565b6001600160a01b0390911660805260a05261007b565b5f5f60408385031215610055575f5ffd5b82516001600160a01b038116811461006b575f5ffd5b6020939093015192949293505050565b60805160a0516105ed6100a95f395f818161010901526102d001525f8181609201526102a101526105ed5ff3fe608060405260043610610041575f3560e01c80635add2f701461004c5780637fab394d14610081578063b61d27f6146100cc578063f003a0c5146100f8575f5ffd5b3661004857005b5f5ffd5b348015610057575f5ffd5b5061006b6100663660046103ed565b610139565b60405161007891906104b7565b60405180910390f35b34801561008c575f5ffd5b506100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610078565b3480156100d7575f5ffd5b506100eb6100e63660046103ed565b610240565b60405161007891906104d0565b348015610103575f5ffd5b5061012b7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610078565b60605f601f61014984601e610505565b610153919061052a565b90505f610161826003610505565b67ffffffffffffffff81111561017957610179610549565b6040519080825280602002602001820160405280156101a2578160200160208202803683370190505b509050866001600160a01b0316815f815181106101c1576101c161055d565b60200260200101818152505085816001815181106101e1576101e161055d565b60200260200101818152505084849050816002815181106102045761020461055d565b60209081029190910101525f5b8281101561023557601f810286013560081c60048201602002830152600101610211565b509695505050505050565b60606001600160a01b038516158061026057506001600160a01b03851630145b1561027e5760405163416aebb560e11b815260040160405180910390fd5b8347101561029f57604051631e9acf1760e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c9dd5c07f00000000000000000000000000000000000000000000000000000000000000006102fb88888888610139565b6040518363ffffffff1660e01b8152600401610318929190610571565b6020604051808303815f875af1158015610334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103589190610591565b505f5f866001600160a01b03168686866040516103769291906105a8565b5f6040518083038185875af1925050503d805f81146103b0576040519150601f19603f3d011682016040523d82523d5f602084013e6103b5565b606091505b5091509150816103e3578060405163a5fa8d2b60e01b81526004016103da91906104d0565b60405180910390fd5b9695505050505050565b5f5f5f5f60608587031215610400575f5ffd5b84356001600160a01b0381168114610416575f5ffd5b935060208501359250604085013567ffffffffffffffff811115610438575f5ffd5b8501601f81018713610448575f5ffd5b803567ffffffffffffffff81111561045e575f5ffd5b87602082840101111561046f575f5ffd5b949793965060200194505050565b5f8151808452602084019350602083015f5b828110156104ad57815186526020958601959091019060010161048f565b5093949350505050565b602081525f6104c9602083018461047d565b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082018082111561052457634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8261054457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f610589604083018461047d565b949350505050565b5f602082840312156105a1575f5ffd5b5051919050565b818382375f910190815291905056fea26469706673582212208e39481fc28d11c7a6da7706c50f24f8b563dca7188a2df30970b65ec546b9ac64736f6c634300081c0033000000000000000000000000c662c410c0ecf747543f5ba90660f6abebd9c8c4053499f7aa2706395060fe72d00388803fb2dcc111429891ad7b2d9dcea29acd", + "nonce": "0x235", + "chainId": "0x1" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x9666a8", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x58d886795afd7ff428175030088865eb35fbe30eae5e963c32a39246904a721f", + "transactionIndex": "0x6e", + "blockHash": "0x39d47bd69be96c71a6b498346659f3099234e962279466f55339fbe2be7772f0", + "blockNumber": "0x149306d", + "gasUsed": "0x5d89b", + "effectiveGasPrice": "0x57a2bad5f", + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "to": null, + "contractAddress": "0xd2f72213a2d1f9d95f10bf4afe2ba8a2fb4868f2" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736266757, + "chain": 1, + "commit": "27ce525" +} \ No newline at end of file diff --git a/l1_proxy/broadcast/Deploy.s.sol/11155111/run-1736266524.json b/l1_proxy/broadcast/Deploy.s.sol/11155111/run-1736266524.json new file mode 100644 index 0000000..fc41c73 --- /dev/null +++ b/l1_proxy/broadcast/Deploy.s.sol/11155111/run-1736266524.json @@ -0,0 +1,49 @@ +{ + "transactions": [ + { + "hash": "0xea670257d53449d27fcd44127d13f0a2c2e44fad2e0727a96055bbc6e6e5a215", + "transactionType": "CREATE", + "contractName": "StarknetOwnerProxy", + "contractAddress": "0x04e99d8f63d325fcea9b36913879bba4732b99af", + "function": null, + "arguments": [ + "0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057", + "2056114384263610425007312686792758172158354636787877809965121556469642730868" + ], + "transaction": { + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "gas": "0x79996", + "value": "0x0", + "input": "0x60c060405234801561000f575f5ffd5b5060405161069638038061069683398101604081905261002e91610044565b6001600160a01b0390911660805260a05261007b565b5f5f60408385031215610055575f5ffd5b82516001600160a01b038116811461006b575f5ffd5b6020939093015192949293505050565b60805160a0516105ed6100a95f395f818161010901526102d001525f8181609201526102a101526105ed5ff3fe608060405260043610610041575f3560e01c80635add2f701461004c5780637fab394d14610081578063b61d27f6146100cc578063f003a0c5146100f8575f5ffd5b3661004857005b5f5ffd5b348015610057575f5ffd5b5061006b6100663660046103ed565b610139565b60405161007891906104b7565b60405180910390f35b34801561008c575f5ffd5b506100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610078565b3480156100d7575f5ffd5b506100eb6100e63660046103ed565b610240565b60405161007891906104d0565b348015610103575f5ffd5b5061012b7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610078565b60605f601f61014984601e610505565b610153919061052a565b90505f610161826003610505565b67ffffffffffffffff81111561017957610179610549565b6040519080825280602002602001820160405280156101a2578160200160208202803683370190505b509050866001600160a01b0316815f815181106101c1576101c161055d565b60200260200101818152505085816001815181106101e1576101e161055d565b60200260200101818152505084849050816002815181106102045761020461055d565b60209081029190910101525f5b8281101561023557601f810286013560081c60048201602002830152600101610211565b509695505050505050565b60606001600160a01b038516158061026057506001600160a01b03851630145b1561027e5760405163416aebb560e11b815260040160405180910390fd5b8347101561029f57604051631e9acf1760e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c9dd5c07f00000000000000000000000000000000000000000000000000000000000000006102fb88888888610139565b6040518363ffffffff1660e01b8152600401610318929190610571565b6020604051808303815f875af1158015610334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103589190610591565b505f5f866001600160a01b03168686866040516103769291906105a8565b5f6040518083038185875af1925050503d805f81146103b0576040519150601f19603f3d011682016040523d82523d5f602084013e6103b5565b606091505b5091509150816103e3578060405163a5fa8d2b60e01b81526004016103da91906104d0565b60405180910390fd5b9695505050505050565b5f5f5f5f60608587031215610400575f5ffd5b84356001600160a01b0381168114610416575f5ffd5b935060208501359250604085013567ffffffffffffffff811115610438575f5ffd5b8501601f81018713610448575f5ffd5b803567ffffffffffffffff81111561045e575f5ffd5b87602082840101111561046f575f5ffd5b949793965060200194505050565b5f8151808452602084019350602083015f5b828110156104ad57815186526020958601959091019060010161048f565b5093949350505050565b602081525f6104c9602083018461047d565b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082018082111561052457634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8261054457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f610589604083018461047d565b949350505050565b5f602082840312156105a1575f5ffd5b5051919050565b818382375f910190815291905056fea26469706673582212208e39481fc28d11c7a6da7706c50f24f8b563dca7188a2df30970b65ec546b9ac64736f6c634300081c0033000000000000000000000000e2bb56ee936fd6433dc0f6e7e3b8365c906aa057048bb83134ce6a312d1b41b0b3deccc4ce9a9d280e6c68c0eb1c517259c89d74", + "nonce": "0x10", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0xeb149f", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xea670257d53449d27fcd44127d13f0a2c2e44fad2e0727a96055bbc6e6e5a215", + "transactionIndex": "0x71", + "blockHash": "0xa253bacd02af40e9479dd58ccecd6bc4eb450f481eeaa64408ec0b1ff6076ea6", + "blockNumber": "0x718a56", + "gasUsed": "0x5d89b", + "effectiveGasPrice": "0x68d7fd1b9", + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "to": null, + "contractAddress": "0x04e99d8f63d325fcea9b36913879bba4732b99af" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736266524, + "chain": 11155111, + "commit": "27ce525" +} \ No newline at end of file diff --git a/l1_proxy/broadcast/Deploy.s.sol/11155111/run-latest.json b/l1_proxy/broadcast/Deploy.s.sol/11155111/run-latest.json new file mode 100644 index 0000000..fc41c73 --- /dev/null +++ b/l1_proxy/broadcast/Deploy.s.sol/11155111/run-latest.json @@ -0,0 +1,49 @@ +{ + "transactions": [ + { + "hash": "0xea670257d53449d27fcd44127d13f0a2c2e44fad2e0727a96055bbc6e6e5a215", + "transactionType": "CREATE", + "contractName": "StarknetOwnerProxy", + "contractAddress": "0x04e99d8f63d325fcea9b36913879bba4732b99af", + "function": null, + "arguments": [ + "0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057", + "2056114384263610425007312686792758172158354636787877809965121556469642730868" + ], + "transaction": { + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "gas": "0x79996", + "value": "0x0", + "input": "0x60c060405234801561000f575f5ffd5b5060405161069638038061069683398101604081905261002e91610044565b6001600160a01b0390911660805260a05261007b565b5f5f60408385031215610055575f5ffd5b82516001600160a01b038116811461006b575f5ffd5b6020939093015192949293505050565b60805160a0516105ed6100a95f395f818161010901526102d001525f8181609201526102a101526105ed5ff3fe608060405260043610610041575f3560e01c80635add2f701461004c5780637fab394d14610081578063b61d27f6146100cc578063f003a0c5146100f8575f5ffd5b3661004857005b5f5ffd5b348015610057575f5ffd5b5061006b6100663660046103ed565b610139565b60405161007891906104b7565b60405180910390f35b34801561008c575f5ffd5b506100b47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610078565b3480156100d7575f5ffd5b506100eb6100e63660046103ed565b610240565b60405161007891906104d0565b348015610103575f5ffd5b5061012b7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610078565b60605f601f61014984601e610505565b610153919061052a565b90505f610161826003610505565b67ffffffffffffffff81111561017957610179610549565b6040519080825280602002602001820160405280156101a2578160200160208202803683370190505b509050866001600160a01b0316815f815181106101c1576101c161055d565b60200260200101818152505085816001815181106101e1576101e161055d565b60200260200101818152505084849050816002815181106102045761020461055d565b60209081029190910101525f5b8281101561023557601f810286013560081c60048201602002830152600101610211565b509695505050505050565b60606001600160a01b038516158061026057506001600160a01b03851630145b1561027e5760405163416aebb560e11b815260040160405180910390fd5b8347101561029f57604051631e9acf1760e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c9dd5c07f00000000000000000000000000000000000000000000000000000000000000006102fb88888888610139565b6040518363ffffffff1660e01b8152600401610318929190610571565b6020604051808303815f875af1158015610334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103589190610591565b505f5f866001600160a01b03168686866040516103769291906105a8565b5f6040518083038185875af1925050503d805f81146103b0576040519150601f19603f3d011682016040523d82523d5f602084013e6103b5565b606091505b5091509150816103e3578060405163a5fa8d2b60e01b81526004016103da91906104d0565b60405180910390fd5b9695505050505050565b5f5f5f5f60608587031215610400575f5ffd5b84356001600160a01b0381168114610416575f5ffd5b935060208501359250604085013567ffffffffffffffff811115610438575f5ffd5b8501601f81018713610448575f5ffd5b803567ffffffffffffffff81111561045e575f5ffd5b87602082840101111561046f575f5ffd5b949793965060200194505050565b5f8151808452602084019350602083015f5b828110156104ad57815186526020958601959091019060010161048f565b5093949350505050565b602081525f6104c9602083018461047d565b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082018082111561052457634e487b7160e01b5f52601160045260245ffd5b92915050565b5f8261054457634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f610589604083018461047d565b949350505050565b5f602082840312156105a1575f5ffd5b5051919050565b818382375f910190815291905056fea26469706673582212208e39481fc28d11c7a6da7706c50f24f8b563dca7188a2df30970b65ec546b9ac64736f6c634300081c0033000000000000000000000000e2bb56ee936fd6433dc0f6e7e3b8365c906aa057048bb83134ce6a312d1b41b0b3deccc4ce9a9d280e6c68c0eb1c517259c89d74", + "nonce": "0x10", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0xeb149f", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xea670257d53449d27fcd44127d13f0a2c2e44fad2e0727a96055bbc6e6e5a215", + "transactionIndex": "0x71", + "blockHash": "0xa253bacd02af40e9479dd58ccecd6bc4eb450f481eeaa64408ec0b1ff6076ea6", + "blockNumber": "0x718a56", + "gasUsed": "0x5d89b", + "effectiveGasPrice": "0x68d7fd1b9", + "from": "0xf94e5cdf41247e268d4847c30a0dc2893b33e85d", + "to": null, + "contractAddress": "0x04e99d8f63d325fcea9b36913879bba4732b99af" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736266524, + "chain": 11155111, + "commit": "27ce525" +} \ No newline at end of file diff --git a/l1_proxy/foundry.toml b/l1_proxy/foundry.toml new file mode 100644 index 0000000..25b918f --- /dev/null +++ b/l1_proxy/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/l1_proxy/lib/forge-std b/l1_proxy/lib/forge-std new file mode 160000 index 0000000..726a6ee --- /dev/null +++ b/l1_proxy/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 726a6ee5fc8427a0013d6f624e486c9130c0e336 diff --git a/l1_proxy/script/Deploy.s.sol b/l1_proxy/script/Deploy.s.sol new file mode 100644 index 0000000..5ba1790 --- /dev/null +++ b/l1_proxy/script/Deploy.s.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {StarknetOwnerProxy, IStarknetMessaging} from "../src/StarknetOwnerProxy.sol"; + +contract CounterScript is Script { + error UnrecognizedChainId(uint256 chainId); + + StarknetOwnerProxy public proxy; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + if (block.chainid == 0x1) { + proxy = new StarknetOwnerProxy( + // Starknet core contract: https://etherscan.io/address/0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4 + IStarknetMessaging(0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4), + // Ekubo governor contract: https://starkscan.co/contract/0x053499f7aa2706395060fe72d00388803fb2dcc111429891ad7b2d9dcea29acd + 0x053499f7aa2706395060fe72d00388803fb2dcc111429891ad7b2d9dcea29acd + ); + } else if (block.chainid == 0xaa36a7) { + proxy = new StarknetOwnerProxy( + // Starknet core contract: https://sepolia.etherscan.io/address/0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057 + IStarknetMessaging(0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057), + // Ekubo governor contract: https://sepolia.starkscan.co/contract/0x048bb83134ce6a312d1b41b0b3deccc4ce9a9d280e6c68c0eb1c517259c89d74 + 0x048bb83134ce6a312d1b41b0b3deccc4ce9a9d280e6c68c0eb1c517259c89d74 + ); + } else { + revert UnrecognizedChainId(block.chainid); + } + + vm.stopBroadcast(); + } +} diff --git a/l1_proxy/src/StarknetOwnerProxy.sol b/l1_proxy/src/StarknetOwnerProxy.sol new file mode 100644 index 0000000..0613742 --- /dev/null +++ b/l1_proxy/src/StarknetOwnerProxy.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.28; + +interface IStarknetMessaging { + function consumeMessageFromL2(uint256 fromAddress, uint256[] calldata payload) external returns (bytes32); +} + +contract StarknetOwnerProxy { + error InvalidTarget(); + error InsufficientBalance(); + error CallFailed(bytes data); + + IStarknetMessaging public immutable l2MessageBridge; + uint256 public immutable l2Owner; + + constructor(IStarknetMessaging _l2MessageBridge, uint256 _l2Owner) { + l2MessageBridge = _l2MessageBridge; + l2Owner = _l2Owner; + } + + // Returns the payload split into 31-byte chunks, + // ensuring each element is < 2^251 + function getPayload(address target, uint256 value, bytes calldata data) public pure returns (uint256[] memory) { + // Each payload element can hold up to 31 bytes since it has to be expressed as felt252 on Starknet + uint256 chunkCount = (data.length + 30) / 31; + uint256[] memory payload = new uint256[](3 + chunkCount); + + payload[0] = uint256(uint160(target)); + payload[1] = value; + payload[2] = data.length; + + for (uint256 i = 0; i < chunkCount; i++) { + assembly ("memory-safe") { + mstore(add(payload, mul(add(i, 4), 32)), shr(8, calldataload(add(data.offset, mul(i, 31))))) + } + } + + return payload; + } + + function execute(address target, uint256 value, bytes calldata data) external returns (bytes memory) { + if (target == address(0) || target == address(this)) { + revert InvalidTarget(); + } + if (address(this).balance < value) revert InsufficientBalance(); + + // Consume message from L2. This will fail if the message has not been sent from L2. + l2MessageBridge.consumeMessageFromL2(l2Owner, getPayload(target, value, data)); + + (bool success, bytes memory result) = target.call{value: value}(data); + if (!success) revert CallFailed(result); + return result; + } + + // Allow contract to receive ETH + receive() external payable {} +} diff --git a/l1_proxy/test/StarknetOwnerProxy.t.sol b/l1_proxy/test/StarknetOwnerProxy.t.sol new file mode 100644 index 0000000..7c95ab7 --- /dev/null +++ b/l1_proxy/test/StarknetOwnerProxy.t.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.28; + +import {Test, console} from "forge-std/Test.sol"; +import {StarknetOwnerProxy, IStarknetMessaging} from "../src/StarknetOwnerProxy.sol"; + +contract StarknetOwnerProxyTest is Test { + StarknetOwnerProxy public proxy; + + function setUp() public { + proxy = new StarknetOwnerProxy(IStarknetMessaging(address(0x1)), 123); + } + + function test_get_payload_empty() public view { + uint256[] memory expected = new uint256[](3); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 0; + assertEq(proxy.getPayload(address(0xdeadbeef), 123, hex""), expected); + } + + function test_get_payload_one_partial_word() public view { + uint256[] memory expected = new uint256[](4); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 3; + expected[3] = 0xabcdef << 224; + assertEq(proxy.getPayload(address(0xdeadbeef), 123, hex"abcdef"), expected); + } + + function test_get_payload_31_bytes() public view { + uint256[] memory expected = new uint256[](4); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 31; + expected[3] = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + assertEq( + proxy.getPayload( + address(0xdeadbeef), 123, hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ), + expected + ); + } + + function test_get_payload_32_bytes() public view { + uint256[] memory expected = new uint256[](5); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 32; + expected[3] = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + expected[4] = 0xff000000000000000000000000000000000000000000000000000000000000; + + assertEq( + proxy.getPayload( + address(0xdeadbeef), 123, hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ), + expected + ); + } + + function test_get_payload_62_bytes() public view { + uint256[] memory expected = new uint256[](5); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 62; + expected[3] = 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd; + expected[4] = 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd; + + assertEq( + proxy.getPayload( + address(0xdeadbeef), + 123, + hex"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd" + ), + expected + ); + } + + function test_get_payload_64_bytes() public view { + uint256[] memory expected = new uint256[](6); + expected[0] = 0xdeadbeef; + expected[1] = 123; + expected[2] = 64; + expected[3] = 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd; + expected[4] = 0xef0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab; + expected[5] = 0xcdef << 232; + + assertEq( + proxy.getPayload( + address(0xdeadbeef), + 123, + hex"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + ), + expected + ); + } +}