Deploy: harden Base mainnet release workflow - #16
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6a213c7d24
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - name: Upload deployment record | ||
| uses: actions/upload-artifact@v4 |
There was a problem hiding this comment.
Preserve the deployment record before verification
If BaseScan verification fails—for example because its API key is missing/invalid or the new contract has not been indexed yet—the upload step is skipped by the workflow's implicit success() condition, even though the preceding mainnet deployment is already irreversible. Upload deployment-base.json before verification or give this step an if: always() guard so every successful broadcast retains its structured deployment record.
Useful? React with 👍 / 👎.
| BASESCAN_API_KEY: ${{ secrets.BASESCAN_API_KEY }} | ||
| run: cd base-agent && npm run deploy:base | ||
| PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY || secrets.PRIVATE_KEY }} | ||
| DESTINATION_ADDRESS: ${{ secrets.DESTINATION_ADDRESS }} |
There was a problem hiding this comment.
Record the contract's actual fixed destination
The root deploy script merely copies this environment value into deployment-base.json, while contracts/AgentExecutor.sol uses the compiled-in DESTINATION constant and never reads DESTINATION_ADDRESS. Consequently, when this undocumented secret is absent the uploaded record says destination: null, and when it differs it records an address to which the deployed contract can never withdraw; derive the field from the deployed contract or validate the secret against its constant.
Useful? React with 👍 / 👎.
| console.log(`Base mainnet chainId verified: ${network.chainId}`); | ||
| console.log(`Deployer address: ${wallet.address}`); | ||
| console.log(`Deployer balance: ${formatEther(balance)} ETH`); | ||
| if (balance === 0n) throw new Error('Deployer has no ETH for gas'); |
There was a problem hiding this comment.
Compare the signer balance with the deployment cost
When the deployer has any dust balance greater than zero but less than the deployment transaction's gas cost, this preflight succeeds even though the gated mainnet deployment is guaranteed to fail with insufficient funds. The check should estimate the AgentExecutor deployment gas and account for current fee data, or enforce a conservative minimum balance, rather than treating every nonzero balance as gas-ready.
Useful? React with 👍 / 👎.
| run: cd base-agent && npm run deploy:base | ||
| PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY || secrets.PRIVATE_KEY }} | ||
| DESTINATION_ADDRESS: ${{ secrets.DESTINATION_ADDRESS }} | ||
| run: npm run deploy:base |
There was a problem hiding this comment.
Deploy with the intended permanent owner
When DEPLOYER_PRIVATE_KEY belongs to the separately recommended deployment wallet, AgentExecutor assigns that signer as owner through owner = msg.sender, even though docs/OWNER_POLICY.md specifies 0xfd1610f5eae31dd757e55d6b4ba543b80a2720b3 as the permanent owner and the contract has no ownership-transfer function. This mainnet deployment therefore leaves the deployer key with permanent executor-administration authority; either construct the contract with the intended owner or reject a signer whose address is not the required owner.
Useful? React with 👍 / 👎.
Hardens the Base mainnet deployment path without broadcasting anything in this PR. Uses the tested root AgentExecutor project, verifies Base chain ID 8453 and signer gas balance, reruns compile/tests, captures the deployed address, verifies on BaseScan, and uploads the deployment record. Keeps the explicit
DEPLOYworkflow-dispatch authorization gate andbase-mainnetenvironment.