Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
e8f8ff3
feat: added initial spec [SV-1100]
supervaulter Jan 21, 2026
d034a9f
chore: cursor feedback
supervaulter Jan 21, 2026
0608169
chore: spec simplified
supervaulter Jan 22, 2026
e694fad
fix: add missing validation checks to PT amortized oracle spec
supervaulter Jan 22, 2026
0750ce1
feat: added initial pendle pt boring strategy pricing oracle [SV-1096]
supervaulter Jan 27, 2026
568b8e3
chore: added claude CI files, cursor fixes, deployment scripts-wip an…
supervaulter Jan 27, 2026
e52e4ea
chore: deployment scripts update + simulation and small fixes
supervaulter Jan 27, 2026
d10a3f2
chore: fixed test
supervaulter Jan 27, 2026
c30d0d8
chore: fix claude PR access
supervaulter Jan 27, 2026
63c7563
chore: added more test to go over coverage threshold
supervaulter Jan 27, 2026
fd218ea
chore: revert on unregsitered amount
supervaulter Jan 27, 2026
99be11a
chore: regenerated bytecode & fixed cursor comments
supervaulter Jan 27, 2026
5ef8a62
chore: removed handling the special case when A_t0 == 0
supervaulter Jan 27, 2026
a5f0aeb
chore: added sellOrderId and regernated bytecode
supervaulter Jan 27, 2026
ff66736
chore: fixed cursor comments
supervaulter Jan 27, 2026
2947f3d
chore: coverage test fix
supervaulter Jan 27, 2026
1ab7498
chore: small fix for fuzz test
supervaulter Jan 27, 2026
7c86fb1
feat: added a simplified oracle version - hook based flow
supervaulter Jan 28, 2026
a9d856f
Merge pull request #283 from superform-xyz/feat/oracle-simplified
supervaulter Jan 28, 2026
58b16c7
chore: regenerated bytecode + scripts fixes
supervaulter Jan 28, 2026
e0de0ec
Merge pull request #284 from superform-xyz/feat/oracle-simplified
supervaulter Jan 28, 2026
645dff2
chore: removed lastUpdatePtAmount
supervaulter Jan 28, 2026
6b0ca96
chore: regenerated bytecode
supervaulter Jan 28, 2026
5efccb5
Merge pull request #282 from superform-xyz/feat/spec-for-pseudo-pt-or…
supervaulter Jan 28, 2026
c6ecb5f
chore: small improvements for upload to s3
supervaulter Jan 28, 2026
639a980
chore: generated local prod latest.json
supervaulter Jan 28, 2026
f7cc6f6
Merge pull request #286 from superform-xyz/chore/upload-to-s3-small-i…
supervaulter Jan 29, 2026
14020c6
feat: added IYieldSourceInteface compatibility to pendle oracle [SV-1…
supervaulter Jan 29, 2026
9c1d375
chore: new pendle oracle [SV-1209]
supervaulter Jan 29, 2026
ccf862a
chore: added argument validation + oracle return logic in case of mat…
supervaulter Jan 29, 2026
1507356
chore: latest prod file
supervaulter Jan 29, 2026
7fc39b1
chore: increased oracle coverage
supervaulter Jan 30, 2026
42da8ba
check for address0 in transfer script
supervaulter Jan 30, 2026
44b2f72
Merge pull request #288 from superform-xyz/feat/pendle-oracle-updates…
supervaulter Jan 30, 2026
d20c032
chore: latest v2-core
supervaulter Feb 3, 2026
7d53b57
Merge pull request #289 from superform-xyz/chore/sync-v2-core
subhasishgoswami Feb 3, 2026
a29450b
chore: added support for hyperevm - periphery
supervaulter Feb 4, 2026
136555b
Merge pull request #290 from superform-xyz/chore/hyperevm-scripts-per…
supervaulter Feb 4, 2026
4b04310
chore: [SV-1279] & [SV-1282] up oracle change test and pendle deth to…
supervaulter Feb 9, 2026
af7d71d
chore: small fixed price oracle fix
supervaulter Feb 10, 2026
bcc4a8e
chore: added batch operator transfer script
supervaulter Feb 10, 2026
986c398
feat: [SV-1330] pendle amortized oracle v2 - wip
supervaulter Feb 11, 2026
aa0deee
chore: use in the new oracle
supervaulter Feb 11, 2026
c78b539
chore: added tests and v1 vs v2 simulations + oracle fixes
supervaulter Feb 11, 2026
d20f6d9
chore: staging deployment + test fix
supervaulter Feb 11, 2026
44a7979
chore: coverage improvement
supervaulter Feb 11, 2026
3fce9f1
feat: scripts preparations for up and superform oracle
supervaulter Feb 16, 2026
fcb9275
chore: deployed up oft and gas oracle on hyperevm
supervaulter Feb 16, 2026
6a2801a
chore: added verification scripts + v2 periphery deployment
supervaulter Feb 16, 2026
fd4b72c
chore: more hyperevm deployments and scripts updates + prod latest js…
supervaulter Feb 17, 2026
8c38a1e
chore: deployed batch operator
supervaulter Feb 17, 2026
9b63b80
feat: pendle amortized oracle merge + simulate and script fixes
supervaulter Feb 17, 2026
c7d63e7
feat: deployed pendle oracle v2
supervaulter Feb 17, 2026
6d5fc2d
feat: staging deployed
supervaulter Feb 17, 2026
a677045
Merge pull request #291 from superform-xyz/chore/oracle-pendle-integr…
supervaulter Feb 18, 2026
357823a
chore: v2-core update
supervaulter Feb 18, 2026
7f80043
Merge pull request #293 from superform-xyz/feat/up-oft-hyperevm
supervaulter Feb 18, 2026
f651fb0
feat: integration tests for SuperBank [SV-1398]
supervaulter Feb 19, 2026
4cd63b7
chore: tests improvements + configure from delegate for oft
supervaulter Feb 20, 2026
ed5b307
Merge pull request #294 from superform-xyz/feat/integration-tests-SV-…
supervaulter Feb 20, 2026
37be5fb
chore: moved pendle oracle to v2-core
supervaulter Feb 23, 2026
a15c274
chore: rmeoved forgatten files
supervaulter Feb 23, 2026
bbbb41c
chore: removed oracles from verification scripts
supervaulter Feb 23, 2026
35fe924
Merge pull request #295 from superform-xyz/chore/oracle-to-core-sv-1408
supervaulter Feb 23, 2026
83329d7
chore: added standard json outputs and updated verification script [S…
supervaulter Feb 27, 2026
87c5428
chore: [SV-247] final coverage for periphery
supervaulter Feb 27, 2026
e344e70
Merge pull request #298 from superform-xyz/chore/coverage-increase
supervaulter Mar 3, 2026
a86581b
Merge pull request #297 from superform-xyz/chore/verification-script-…
supervaulter Mar 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage

Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.

Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.

# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
49 changes: 49 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: read
Copy link

Choose a reason for hiding this comment

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

Workflow has insufficient permissions to comment on issues

Medium Severity

The claude.yml workflow triggers on issues: [opened, assigned] and issue_comment: [created] events (lines 4–9), but the permissions block only grants issues: read (line 24). The official claude-code-action example and documentation specify issues: write is required for Claude to post response comments. With issues: read, Claude will process the request but silently fail to respond when triggered from an issue or issue comment containing @claude.

Fix in Cursor Fix in Web

id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'
193 changes: 193 additions & 0 deletions script/DeployPendlePTAmortizedOracle.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.30;

import { PendlePTAmortizedOracleScriptBase } from "./PendlePTAmortizedOracleScriptBase.s.sol";
import { PendlePTAmortizedOracle } from "../src/oracles/vaults/PendlePTAmortizedOracle.sol";
import { console2 } from "forge-std/console2.sol";

/// @title DeployPendlePTAmortizedOracle
/// @notice Deployment script for PendlePTAmortizedOracle - amortized cost pricing for Pendle PT positions
/// @dev Deploys across multiple chains with deterministic addresses
/// @dev Initially grants all roles to DEPLOYER for operational flexibility, then transfers to SUPER_GOVERNOR later
contract DeployPendlePTAmortizedOracle is PendlePTAmortizedOracleScriptBase {
/*//////////////////////////////////////////////////////////////
MAIN FUNCTIONS
//////////////////////////////////////////////////////////////*/

/// @notice Deploy PendlePTAmortizedOracle on a single chain
/// @dev Grants all roles (DEFAULT_ADMIN_ROLE, MANAGER_ROLE) to DEPLOYER
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param chainId Chain ID to deploy on
/// @param branchName Branch name for vnet deployments (required when env == 1, ignored otherwise)
function run(uint256 env, uint64 chainId, string calldata branchName) external broadcast(env) {
_validateEnvAndBranchName(env, branchName);
// Use DEPLOYER as admin - will be transferred to SUPER_GOVERNOR_ADDRESS later
address admin = DEPLOYER;
_deploy(env, chainId, admin, branchName);
}

/// @notice Deploy PendlePTAmortizedOracle on multiple chains
/// @dev Grants all roles (DEFAULT_ADMIN_ROLE, MANAGER_ROLE) to DEPLOYER
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param chainIds Array of chain IDs to deploy on
/// @param branchName Branch name for vnet deployments (required when env == 1, ignored otherwise)
function runMultiChain(uint256 env, uint64[] calldata chainIds, string calldata branchName) external broadcast(env) {
_validateEnvAndBranchName(env, branchName);
// Use DEPLOYER as admin - will be transferred to SUPER_GOVERNOR_ADDRESS later
address admin = DEPLOYER;

console2.log("====== Deploying PendlePTAmortizedOracle (Multi-Chain) ======");
console2.log("Environment:", env);
if (env == 1) {
console2.log("Branch Name:", branchName);
}
console2.log("Admin (DEPLOYER):", admin);
console2.log("Number of chains:", chainIds.length);
console2.log("");

for (uint256 i = 0; i < chainIds.length; i++) {
_deploy(env, chainIds[i], admin, branchName);
console2.log("");
}

console2.log("====== Multi-Chain Deployment Complete ======");
}

/// @notice Check if PendlePTAmortizedOracle is deployed
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param chainId Chain ID to check
/// @param branchName Branch name for vnet deployments (required when env == 1, ignored otherwise)
function runCheck(uint256 env, uint64 chainId, string calldata branchName) external broadcast(env) {
_validateEnvAndBranchName(env, branchName);
_setBaseConfiguration(env, branchName);

// Check with DEPLOYER as admin (initial deployment)
address admin = DEPLOYER;

console2.log("====== PendlePTAmortizedOracle Deployment Check ======");
console2.log("Chain ID:", chainId);
console2.log("Environment:", env);
if (env == 1) {
console2.log("Branch Name:", branchName);
}
console2.log("Admin (DEPLOYER):", admin);
console2.log("SUPER_GOVERNOR_ADDRESS:", SUPER_GOVERNOR_ADDRESS);
console2.log("");

address oracleAddr = _computeOracleAddress(env, admin);
bool isDeployed = oracleAddr.code.length > 0;

console2.log("Computed address:", oracleAddr);
console2.log("Is deployed:", isDeployed);

if (isDeployed) {
PendlePTAmortizedOracle oracle = PendlePTAmortizedOracle(oracleAddr);
console2.log("");
console2.log("=== Oracle Role Status ===");
console2.log("DEPLOYER has DEFAULT_ADMIN_ROLE:", oracle.hasRole(oracle.DEFAULT_ADMIN_ROLE(), admin));
console2.log("DEPLOYER has MANAGER_ROLE:", oracle.hasRole(oracle.MANAGER_ROLE(), admin));
console2.log("");
console2.log("SUPER_GOVERNOR has DEFAULT_ADMIN_ROLE:", oracle.hasRole(oracle.DEFAULT_ADMIN_ROLE(), SUPER_GOVERNOR_ADDRESS));
console2.log("SUPER_GOVERNOR has MANAGER_ROLE:", oracle.hasRole(oracle.MANAGER_ROLE(), SUPER_GOVERNOR_ADDRESS));
}

console2.log("");
console2.log("====== Check Complete ======");
}

/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/

/// @notice Internal deployment function
/// @dev Grants all roles (DEFAULT_ADMIN_ROLE, MANAGER_ROLE) to admin
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param chainId Chain ID to deploy on
/// @param admin Admin address (DEPLOYER)
/// @param branchName Branch name for vnet deployments
function _deploy(uint256 env, uint64 chainId, address admin, string calldata branchName) internal {
_setBaseConfiguration(env, branchName);

console2.log("====== Deploying PendlePTAmortizedOracle ======");
console2.log("Chain ID:", chainId);
console2.log("Environment:", env);
if (env == 1) {
console2.log("Branch Name:", branchName);
}
console2.log("Admin (DEPLOYER):", admin);
console2.log("");

// Validate inputs
require(admin != address(0), "INVALID_ADMIN");

// Get bytecode from generated artifacts
bytes memory bytecode = __getBytecode(ORACLE_KEY, env);
require(bytecode.length > 0, "BYTECODE_NOT_FOUND");

// Deploy - constructor grants DEFAULT_ADMIN_ROLE and MANAGER_ROLE to admin
address oracleAddr = __deployContract(
ORACLE_KEY,
chainId,
__getSalt(ORACLE_KEY),
abi.encodePacked(bytecode, abi.encode(admin))
);

// Verify deployment
PendlePTAmortizedOracle oracle = PendlePTAmortizedOracle(oracleAddr);
require(oracle.hasRole(oracle.DEFAULT_ADMIN_ROLE(), admin), "ADMIN_ROLE_MISMATCH");
require(oracle.hasRole(oracle.MANAGER_ROLE(), admin), "MANAGER_ROLE_MISMATCH");

console2.log("");
console2.log("=== Deployment Verification ===");
console2.log("PendlePTAmortizedOracle deployed at:", oracleAddr);
console2.log("Admin verified:", admin);
console2.log("Has DEFAULT_ADMIN_ROLE:", true);
console2.log("Has MANAGER_ROLE:", true);

// Write JSON output
_writeOracleJson(env, chainId, oracleAddr, branchName);

console2.log("");
console2.log("====== Deployment Complete ======");
}

/// @notice Merge PendlePTAmortizedOracle address into {ChainName}-latest.json
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param chainId Chain ID
/// @param oracleAddr Deployed oracle address
/// @param branchName Branch name for vnet deployments
function _writeOracleJson(
uint256 env,
uint64 chainId,
address oracleAddr,
string calldata branchName
)
internal
{
string memory root = vm.projectRoot();
string memory envFolder;
if (env == 0) {
envFolder = "prod";
} else if (env == 1) {
envFolder = branchName;
} else {
envFolder = "staging";
}

string memory chainName = chainNames[chainId];
string memory outputFolder =
string(abi.encodePacked(root, "/script/output/", envFolder, "/", vm.toString(uint256(chainId)), "/"));

// Create directory if it doesn't exist
vm.createDir(outputFolder, true);

string memory outputPath = string(abi.encodePacked(outputFolder, chainName, "-latest.json"));

// Merge PendlePTAmortizedOracle address into existing JSON
// vm.writeJson with path selector will create file if it doesn't exist or update existing
vm.writeJson(vm.toString(oracleAddr), outputPath, ".PendlePTAmortizedOracle");

console2.log("");
console2.log("PendlePTAmortizedOracle merged into:", outputPath);
}
}
10 changes: 0 additions & 10 deletions script/DeploySuperVaultBatchOperator.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,6 @@ contract DeploySuperVaultBatchOperator is DeployV2Base {
console2.log("====== Check Complete ======");
}

/// @notice Validate environment and branchName combination
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param branchName Branch name (required for vnet)
function _validateEnvAndBranchName(uint256 env, string calldata branchName) internal pure {
require(env == 0 || env == 1 || env == 2, "INVALID_ENV");
if (env == 1) {
require(bytes(branchName).length > 0, "BRANCH_NAME_REQUIRED_FOR_VNET");
}
}

/// @notice Get operator address based on environment
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
function _getOperatorForEnv(uint256 env) internal pure returns (address) {
Expand Down
14 changes: 14 additions & 0 deletions script/DeployV2Base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ abstract contract DeployV2Base is Script, ConfigBase {
}
}

/*//////////////////////////////////////////////////////////////
ENV VALIDATION
//////////////////////////////////////////////////////////////*/

/// @notice Validate environment and branchName combination
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param branchName Branch name (required for vnet)
function _validateEnvAndBranchName(uint256 env, string calldata branchName) internal pure {
require(env == 0 || env == 1 || env == 2, "INVALID_ENV");
if (env == 1) {
require(bytes(branchName).length > 0, "BRANCH_NAME_REQUIRED_FOR_VNET");
}
}

function _getContract(uint64 chainId, string memory contractName) internal view returns (address) {
return contractAddresses[chainId][contractName];
}
Expand Down
34 changes: 34 additions & 0 deletions script/PendlePTAmortizedOracleScriptBase.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.30;

import { DeployV2Base } from "./DeployV2Base.s.sol";
import { DeterministicDeployerLib } from "lib/v2-core/src/vendor/nexus/DeterministicDeployerLib.sol";

/// @title PendlePTAmortizedOracleScriptBase
/// @notice Shared base contract for PendlePTAmortizedOracle deployment and ownership scripts
/// @dev Contains common constants and utility functions
abstract contract PendlePTAmortizedOracleScriptBase is DeployV2Base {
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/

/// @notice Contract key for PendlePTAmortizedOracle
string internal constant ORACLE_KEY = "PendlePTAmortizedOracle";

/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/

/// @notice Compute the deterministic address for PendlePTAmortizedOracle
/// @param env Environment (0 = prod, 1 = vnet, 2 = staging)
/// @param admin Admin address used during deployment
/// @return The computed deterministic address
function _computeOracleAddress(uint256 env, address admin) internal view returns (address) {
bytes memory bytecode = __getBytecode(ORACLE_KEY, env);
require(bytecode.length > 0, "BYTECODE_NOT_FOUND");
return DeterministicDeployerLib.computeAddress(
abi.encodePacked(bytecode, abi.encode(admin)),
__getSalt(ORACLE_KEY)
);
}
}
Loading
Loading