Skip to content

Commit

Permalink
Defender Actions setup (#12)
Browse files Browse the repository at this point in the history
* WIP outstanding requests

* Got autoClaimWithdraw Hardhat task working

* Added setActionVars Hardhat task
Got Defender Actions working

* Add await for contract.getAddress()

* Downgrade to ethers v5
  • Loading branch information
naddison36 authored Aug 16, 2024
1 parent d959a32 commit 8af08d0
Show file tree
Hide file tree
Showing 18 changed files with 577 additions and 103 deletions.
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,19 @@ forge verify-contract 0x6bac785889A4127dB0e0CeFEE88E0a9F1Aaf3cC7 Proxy

[Open Zeppelin Defender v2](https://docs.openzeppelin.com/defender/v2/) is used to manage the Operations account and automate AMM operational jobs like managing liquidity.

### Deploying Defender Autotasks
### Deploying Defender Actions

Autotasks are used to run operational jobs are specific times or intervals.
Defender Actions are used to run operational jobs are specific times or intervals.

[rollup](https://rollupjs.org/) is used to bundle the Autotask source code in [/src/js/autotasks](./src/js/autotasks) into a single file that can be uploaded to Defender. The implementation was based off [Defender Autotask example using Rollup](https://github.com/OpenZeppelin/defender-autotask-examples/tree/master/rollup). The rollup config is in [/src/js/autotasks/rollup.config.cjs](./src/js/autotasks/rollup.config.cjs). The outputs are written to task-specific folders under [/src/js/autotasks/dist](./src/js/autotasks/dist/).
[rollup](https://rollupjs.org/) is used to bundle the Actions source code in [/src/js/actions](./src/js/actions) into a single file that can be uploaded to Defender. The implementation was based off [Defender Action example using Rollup](https://github.com/OpenZeppelin/defender-autotask-examples/tree/master/rollup). The rollup config is in [/src/js/actions/rollup.config.cjs](./src/js/actions/rollup.config.cjs). The outputs are written to task-specific folders under [/src/js/actions/dist](./src/js/actions/dist/).

The [defender-autotask CLI](https://www.npmjs.com/package/@openzeppelin/defender-autotask-client) is used to upload the Action code to Defender.
For this to work, a Defender Team API key with `Manage Actions` capabilities is needed. This can be generated by a Defender team admin under the `Manage` tab on the top right of the UI and then `API Keys` on the left menu.

The following will set the Defender Team API key and bundle the Autotask code ready for upload.
The following will set the Defender Team API key and bundle the Actions code ready for upload.

```
cd ./src/js/autotasks
```bash
cd ./src/js/actions

# Export the Defender Team API key. This is different to the Defender Relayer API key.
export API_KEY=
Expand All @@ -225,13 +225,21 @@ export API_SECRET=
npx rollup -c
```

The following will upload the different Autotask bundles to Defender.
The following will upload the different Action bundles to Defender.

```
# autoRequestWithdraw
```bash

# autoClaimWithdraws
# Set the DEBUG environment variable to oeth* for the Defender Action
npx hardhat setActionVars --id 93c010f9-05b5-460f-bd10-1205dd80a7c9
npx hardhat setActionVars --id 563d8d0c-17dc-46d3-8955-e4824864869f

# The Defender autotask client uses generic env var names so we'll set them first from the values in the .env file
export API_KEY=
export API_SECRET=

# Mainnet
npx defender-autotask update-code 93c010f9-05b5-460f-bd10-1205dd80a7c9 ./dist/autoRequestWithdraw
npx defender-autotask update-code 563d8d0c-17dc-46d3-8955-e4824864869f ./dist/autoClaimWithdraw
```

`rollup` and `defender-autotask` can be installed globally to avoid the `npx` prefix.
2 changes: 1 addition & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require("dotenv").config();

require("@nomicfoundation/hardhat-ethers");
require("@nomiclabs/hardhat-ethers");
require("@nomicfoundation/hardhat-foundry");

require("./src/js/tasks/tasks");
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,24 @@
},
"license": "MIT",
"devDependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.5",
"@apollo/client": "^3.11.4",
"@nomiclabs/hardhat-ethers": "2.0.2",
"@nomicfoundation/hardhat-foundry": "^1.1.1",
"@nomicfoundation/hardhat-network-helpers": "^1.0.10",
"@openzeppelin/defender-autotask-client": "^1.54.1",
"@openzeppelin/defender-sdk": "^1.11.0",
"@openzeppelin/defender-sdk": "1.13.1",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@solidity-parser/parser": "^0.18.0",
"axios": "^1.6.2",
"builtin-modules": "^3.3.0",
"chai": "^4.3.10",
"dayjs": "^1.11.12",
"dotenv": "^16.4.5",
"eslint": "^8.55.0",
"ethers": "^6.11.1",
"ethers": "5.7.2",
"graphql": "^16.9.0",
"hardhat": "^2.19.2",
"rollup": "^4.9.1"
}
Expand Down
236 changes: 236 additions & 0 deletions src/abis/vault.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
[
{
"inputs": [],
"name": "CLAIM_DELAY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "addWithdrawalQueueLiquidity",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"name": "claimWithdrawal",
"outputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256[]",
"name": "requestIds",
"type": "uint256[]"
}
],
"name": "claimWithdrawals",
"outputs": [
{
"internalType": "uint256[]",
"name": "amounts",
"type": "uint256[]"
},
{
"internalType": "uint256",
"name": "totalAmount",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "dripper",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "governor",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_asset",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_minimumOusdAmount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_minimumUnitAmount",
"type": "uint256"
}
],
"name": "redeem",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "requestWithdrawal",
"outputs": [
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "queued",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxSupplyDiff",
"type": "uint256"
}
],
"name": "setMaxSupplyDiff",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "withdrawalQueueMetadata",
"outputs": [
{
"internalType": "uint128",
"name": "queued",
"type": "uint128"
},
{
"internalType": "uint128",
"name": "claimable",
"type": "uint128"
},
{
"internalType": "uint128",
"name": "claimed",
"type": "uint128"
},
{
"internalType": "uint128",
"name": "nextWithdrawalIndex",
"type": "uint128"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "requestId",
"type": "uint256"
}
],
"name": "withdrawalRequests",
"outputs": [
{
"internalType": "address",
"name": "withdrawer",
"type": "address"
},
{
"internalType": "bool",
"name": "claimed",
"type": "bool"
},
{
"internalType": "uint40",
"name": "timestamp",
"type": "uint40"
},
{
"internalType": "uint128",
"name": "amount",
"type": "uint128"
},
{
"internalType": "uint128",
"name": "queued",
"type": "uint128"
}
],
"stateMutability": "view",
"type": "function"
}
]
8 changes: 5 additions & 3 deletions src/contracts/Interfaces.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,21 @@ interface IOETHVault {

function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;

function governor() external returns (address);
function governor() external view returns (address);

function dripper() external returns (address);
function dripper() external view returns (address);

function withdrawalQueueMetadata()
external
view
returns (uint128 queued, uint128 claimable, uint128 claimed, uint128 nextWithdrawalIndex);

function withdrawalRequests(uint256 requestId)
external
view
returns (address withdrawer, bool claimed, uint40 timestamp, uint128 amount, uint128 queued);

function CLAIM_DELAY() external returns (uint256);
function CLAIM_DELAY() external view returns (uint256);
}

interface IGovernance {
Expand Down
41 changes: 41 additions & 0 deletions src/js/actions/autoClaimWithdraw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const {
DefenderRelaySigner,
DefenderRelayProvider,
} = require("defender-relay-client/lib/ethers");
const { ethers } = require("ethers");

const { autoClaimWithdraw } = require("../tasks/liquidity");
const { mainnet } = require("../utils/addresses");
const erc20Abi = require("../../abis/ERC20.json");
const oethARMAbi = require("../../abis/OethARM.json");
const vaultAbi = require("../../abis/vault.json");

// Entrypoint for the Autotask
const handler = async (event) => {
// Initialize defender relayer provider and signer
const provider = new DefenderRelayProvider(event);
const signer = new DefenderRelaySigner(event, provider, { speed: "fastest" });

console.log(
`DEBUG env var in handler before being set: "${process.env.DEBUG}"`
);

// References to contracts
const weth = new ethers.Contract(mainnet.WETH, erc20Abi, signer);
const vault = new ethers.Contract(mainnet.OETHVaultProxy, vaultAbi, signer);
const oethARM = new ethers.Contract(mainnet.OethARM, oethARMAbi, signer);

try {
await autoClaimWithdraw({
signer,
weth,
oethARM,
vault,
confirm: false,
});
} catch (error) {
console.error(error);
}
};

module.exports = { handler };
Loading

0 comments on commit 8af08d0

Please sign in to comment.