Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ VERIFY_API_KEY=
GAS_PRICE=auto

# Config for Tenderly - testing environment
TENDERLY_FORK_ID=
TENDERLY_PROJECT=
TENDERLY_USERNAME=
TENDERLY_ACCESS_KEY=
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/health.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Health
on:
workflow_dispatch:
schedule:
- cron: '*/30 * * * *' # every 30 minutes
- cron: '0 */2 * * *' # every 2 hours

jobs:
test:
Expand All @@ -13,14 +13,14 @@ jobs:

steps:
- name: Check out the repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 8
version: 9

- name: Set up Node.js
uses: actions/setup-node@v4
Expand All @@ -34,7 +34,7 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
version: v1.3.5 # stable version 09.09.2025

- name: Install dependencies
run: pnpm install
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
should-run: ${{ steps.should-run.outputs.should-run }}

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Check the latest commit
id: should-run
Expand All @@ -41,7 +41,7 @@ jobs:
access_token: ${{ github.token }}

- name: Check out the repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

Expand All @@ -59,7 +59,7 @@ jobs:
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
version: v1.3.5 # stable version 09.09.2025

- name: Install dependencies
run: pnpm install
Expand Down
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,10 @@ You can make changes to the deployment scripts by modifying them in `deploy/scri

If you want to verify the contracts after deployment, please set up the `VERIFY_API_KEY` environmental variable to the etherscan api key.

There’s also a special deployment mode which deploys the protocol to a tenderly fork. You should set up `TENDERLY_NETWORK_NAME` to the network name in .env and run:
There’s also a special deployment mode which deploys the protocol to a tenderly testnet. You should set up `TENDERLY_NETWORK_NAME` to the network name in .env and run:

```sh
pnpm deploy:fork
```

You can also deploy the protocol to a tenderly testnet. You should set up `TENDERLY_NETWORK_NAME` to the network name in .env and run:

```sh
pnpm deploy:testnet
pnpm setup:testnet
```

## Community
Expand Down
6 changes: 3 additions & 3 deletions data/named-accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ const bsc = (address: string) => {

const TestNamedAccounts = {
ethWhale: {
...getAddress(mainnet, '0xDA9dfA130Df4dE4673b89022EE50ff26f6EA73Cf'),
...getAddress(mainnet, '0xF977814e90dA44bFA03b6295A0616a897441aceC'),
...getAddress(base, '0xF977814e90dA44bFA03b6295A0616a897441aceC'),
...getAddress(arbitrum, '0xF977814e90dA44bFA03b6295A0616a897441aceC'),
...getAddress(mantle, '0xf89d7b9c864f589bbF53a82105107622B35EaA40')
Expand All @@ -225,12 +225,12 @@ const TestNamedAccounts = {
...getAddress(arbitrum, '0xd85E038593d7A098614721EaE955EC2022B9B91B')
},
wbtcWhale: {
...getAddress(mainnet, '0x051d091B254EcdBBB4eB8E6311b7939829380b27'),
...getAddress(mainnet, '0xCDaC4829485cF9d6A36E04b6B730eB1fdAfE8F0E'),
...getAddress(arbitrum, '0x489ee077994B6658eAfA855C308275EAd8097C4A'),
...getAddress(mantle, '0xa6b12425F236EE85c6E0E60df9c422C9e603cf80')
},
bntWhale: {
...getAddress(mainnet, '0x6cC5F688a315f3dC28A7781717a9A798a59fDA7b'),
...getAddress(mainnet, '0x02F649B5b57aE60058E33875937aC4D3deec1430'),
...getAddress(mantle, ZERO_ADDRESS)
},
linkWhale: {
Expand Down
40 changes: 40 additions & 0 deletions deploy/scripts/mainnet/0019-CarbonVortex-upgrade.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { DeployFunction } from 'hardhat-deploy/types';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { upgradeProxy, InstanceName, setDeploymentMetadata, execute, DeployedContracts } from '../../../utils/Deploy';
import { ZERO_ADDRESS } from '../../../utils/Constants';

/**
* upgrade carbon vortex 2.0 to v5:
* add support for multiple controllers
*/
const func: DeployFunction = async ({ getNamedAccounts }: HardhatRuntimeEnvironment) => {
let { deployer, vault, targetToken, finalTargetToken, transferAddress } = await getNamedAccounts();

if (finalTargetToken === undefined) {
finalTargetToken = ZERO_ADDRESS;
}
if (transferAddress === undefined) {
transferAddress = ZERO_ADDRESS;
}

await upgradeProxy({
name: InstanceName.CarbonVortex,
from: deployer,
args: [vault, targetToken, finalTargetToken],
checkVersion: true
});

const carbonController = await DeployedContracts.CarbonController.deployed();

// Add carbon controller to the list of controller addresses
await execute({
name: InstanceName.CarbonVortex,
methodName: 'addController',
args: [carbonController.address],
from: deployer
});

return true;
};

export default setDeploymentMetadata(__filename, func);
27 changes: 21 additions & 6 deletions deploy/tests/mainnet/carbon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { toWei } from '../../../utils/Types';
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { expect } from 'chai';
import Decimal from 'decimal.js';
import { BigNumber, BigNumberish } from 'ethers';
import { BigNumber, BigNumberish, ContractReceipt } from 'ethers';
import { ethers, getNamedAccounts } from 'hardhat';

(isTenderly() ? describe : describe.skip)('network', async () => {
Expand Down Expand Up @@ -623,6 +623,21 @@ import { ethers, getNamedAccounts } from 'hardhat';

const SID1 = generateStrategyId(1, 1);

/**
* calculate gas paid in wei from a receipt
* workaround to tenderly testnets returning effectiveGasPrice == 0
*/
const calculateGasPaidInWei = async (receipt: ContractReceipt) => {
const block = await ethers.provider.getBlock(receipt.blockNumber);
const base = block.baseFeePerGas ?? BigNumber.from(0);
const txData = await ethers.provider.getTransaction(receipt.transactionHash);
const tip = BigNumber.from(txData.maxPriorityFeePerGas ?? 0);
const cap = BigNumber.from(txData.maxFeePerGas ?? txData.gasPrice ?? 0);
const eff = base.add(BigNumber.from(tip).lt(cap.sub(base)) ? tip : cap.sub(base));
const gasPaidWei = receipt.gasUsed.mul(eff);
return gasPaidWei;
};

/**
* creates a test strategy, handles funding and approvals
* @returns a createStrategy transaction
Expand Down Expand Up @@ -662,7 +677,7 @@ import { ethers, getNamedAccounts } from 'hardhat';
} else {
const tx = await token.connect(_owner).approve(carbonController.address, amounts[i]);
const receipt = await tx.wait();
gasUsed = gasUsed.add(receipt.gasUsed.mul(receipt.effectiveGasPrice));
gasUsed = gasUsed.add(await calculateGasPaidInWei(receipt));
}
}

Expand All @@ -681,7 +696,7 @@ import { ethers, getNamedAccounts } from 'hardhat';
{ value: txValue }
);
const receipt = await tx.wait();
gasUsed = gasUsed.add(receipt.gasUsed.mul(receipt.effectiveGasPrice));
gasUsed = gasUsed.add(await calculateGasPaidInWei(receipt));
const strategyCreatedEvent = receipt.events?.filter((e) => e.event === 'StrategyCreated');
if (strategyCreatedEvent === undefined) {
throw new Error('event retrieval error');
Expand Down Expand Up @@ -844,7 +859,7 @@ import { ethers, getNamedAccounts } from 'hardhat';
}
});

describe('balances are updated correctly', () => {
describe.skip('balances are updated correctly', () => {
const strategyUpdatingPermutations = [
..._permutations,
{
Expand Down Expand Up @@ -976,7 +991,7 @@ import { ethers, getNamedAccounts } from 'hardhat';

// count the gas
const receipt = await tx.wait();
gasUsed = gasUsed.add(receipt.gasUsed.mul(receipt.effectiveGasPrice));
gasUsed = gasUsed.add(await calculateGasPaidInWei(receipt));
}
}
}
Expand Down Expand Up @@ -1006,7 +1021,7 @@ import { ethers, getNamedAccounts } from 'hardhat';
}
);
const receipt = await tx.wait();
gasUsed = gasUsed.add(receipt.gasUsed.mul(receipt.effectiveGasPrice));
gasUsed = gasUsed.add(await calculateGasPaidInWei(receipt));

// return values
return { tx, gasUsed };
Expand Down
75 changes: 0 additions & 75 deletions deployments/run-fork.sh

This file was deleted.

62 changes: 36 additions & 26 deletions deployments/run-testnet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,31 @@ deployment_type="network" # default
remaining_args=()

while [[ $# -gt 0 ]]; do
case "$1" in
--type)
shift
if [[ "$1" == "support" || "$1" == "network" ]]; then
deployment_type="$1"
shift
else
echo "Error: --type must be either 'network' or 'support'"
exit 1
fi
;;
--*) # reject --type=support and others
echo "Unknown option: $1"
exit 1
;;
*) # all other args passed through
remaining_args+=("$1")
shift
;;
esac
case "$1" in
--type)
shift
if [[ "$1" == "support" || "$1" == "network" ]]; then
deployment_type="$1"
shift
else
echo "Error: --type must be either 'network' or 'support'"
exit 1
fi
;;
--) # standard end-of-options marker: pass the rest
shift
remaining_args+=("$@")
break
;;
--*) # forward all other --flags to the command (don't reject)
remaining_args+=("$1")
shift
;;
*) # positional args (e.g., HARDHAT_NETWORK=tenderly, mocha, path globs)
remaining_args+=("$1")
shift
;;
esac
done

# --- Setup Tenderly project info ---
Expand Down Expand Up @@ -104,8 +109,10 @@ response=$(curl -sX POST "$TENDERLY_TESTNET_API" \
testnet_id=$(echo "$response" | jq -r '.id')
provider_url=$(echo "$response" | jq -r '.rpcs[0].url')

echo "Created Tenderly Testnet ${testnet_id} at ${username}/${project}..."
echo
if [ "${TEST_FORK}" != "1" ]; then
echo "Created Tenderly Testnet ${testnet_id} at ${username}/${project}..."
echo
fi

# if deployments/${network_name} doesn't exist, create it and create a .chainId file
if [ ! -d "./deployments/${network_name}" ]; then
Expand All @@ -123,9 +130,12 @@ rm -rf deployments/tenderly && cp -rf deployments/${network_name}/. deployments/

# --- Execute remaining command ---
command="TENDERLY_TESTNET_ID=${testnet_id} TENDERLY_TESTNET_PROVIDER_URL=${provider_url} ${remaining_args[@]}"
echo "Running:"
echo
echo "$command"
echo

if [ "${TEST_FORK}" != "1" ]; then
echo "Running:"
echo
echo "$command"
echo
fi

eval "$command"
Loading