Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

carbon vortex - minor fixes #168

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
127 changes: 79 additions & 48 deletions contracts/vortex/CarbonVortex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
ICarbonController private immutable _carbonController;
IVault private immutable _vault;

// address for token collection - collects all swapped target/final target tokens
address payable private immutable _transferAddress;

// first token for swapping
Token private immutable _targetToken;
// second (optional) token for swapping
Expand Down Expand Up @@ -89,52 +86,52 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
// initial and current target token sale amount - for targetToken->finalTargetToken trades
SaleAmount private _targetTokenSaleAmount;

// address for token collection - collects all swapped target/final target tokens
address payable private _transferAddress;

// upgrade forward-compatibility storage gap
uint256[MAX_GAP - 7] private __gap;
uint256[MAX_GAP - 8] private __gap;

/**
* @dev used to set immutable state variables and initialize the implementation
* @dev used to set immutable state variables
*/
constructor(
ICarbonController carbonController,
IVault vault,
address payable transferAddress,
Token targetTokenInit,
Token finalTargetTokenInit
) validAddress(transferAddress) validAddress(Token.unwrap(targetTokenInit)) {
) validAddress(Token.unwrap(targetTokenInit)) {
_carbonController = carbonController;
_vault = vault;

_transferAddress = transferAddress;

_targetToken = targetTokenInit;
_finalTargetToken = finalTargetTokenInit;
initialize();
_disableInitializers();
}

/**
* @dev fully initializes the contract and its parents
*/
function initialize() public initializer {
__CarbonVortex_init();
function initialize(address payable transferAddressInit) public initializer {
__CarbonVortex_init(transferAddressInit);
}

// solhint-disable func-name-mixedcase

/**
* @dev initializes the contract and its parents
*/
function __CarbonVortex_init() internal onlyInitializing {
function __CarbonVortex_init(address payable transferAddressInit) internal onlyInitializing {
__Upgradeable_init();
__ReentrancyGuard_init();

__CarbonVortex_init_unchained();
__CarbonVortex_init_unchained(transferAddressInit);
}

/**
* @dev performs contract-specific initialization
*/
function __CarbonVortex_init_unchained() internal onlyInitializing {
function __CarbonVortex_init_unchained(address payable transferAddressInit) internal onlyInitializing {
// set rewards PPM to 1000
_setRewardsPPM(1000);
// set price reset multiplier to 2x
Expand All @@ -151,6 +148,8 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
_setMaxTargetTokenSaleAmount(uint128(100) * uint128(10) ** _targetToken.decimals());
// set min target token sale amount to 10 eth
_setMinTokenSaleAmount(_targetToken, uint128(10) * uint128(10) ** _targetToken.decimals());
// set transfer address
_setTransferAddress(transferAddressInit);
}

/**
Expand Down Expand Up @@ -178,7 +177,7 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
* @inheritdoc Upgradeable
*/
function version() public pure override(IVersioned, Upgradeable) returns (uint16) {
return 3;
return 4;
}

/**
Expand Down Expand Up @@ -294,6 +293,17 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
_setPairDisabled(token, disabled);
}

/**
* @notice sets the transfer address
*
* requirements:
*
* - the caller must be the current admin of the contract
*/
function setTransferAddress(address newTransferAddress) external onlyAdmin {
_setTransferAddress(newTransferAddress);
}

/**
* @dev withdraws funds held by the contract and sends them to an account
*
Expand Down Expand Up @@ -346,6 +356,13 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
return _finalTargetToken;
}

/**
* @inheritdoc ICarbonVortex
*/
function transferAddress() external view returns (address) {
return _transferAddress;
}

/**
* @inheritdoc ICarbonVortex
*/
Expand Down Expand Up @@ -402,25 +419,23 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
for (uint256 i = 0; i < len; i = uncheckedInc(i)) {
Token token = tokens[i];
uint256 totalFeeAmount = feeAmounts[i];
// skip the final target token
if (token == _finalTargetToken) {
continue;
}
// get fee and reward amounts
uint256 rewardAmount = rewardAmounts[i];
uint256 feeAmount = totalFeeAmount - rewardAmount;
// skip token if no fees have accumulated or token pair is disabled
if (totalFeeAmount == 0 || _disabledPairs[token]) {
continue;
}
// get fee and reward amounts
uint256 rewardAmount = rewardAmounts[i];
uint256 feeAmount = totalFeeAmount - rewardAmount;
// transfer proceeds to the transfer address for the final target token
if (token == _finalTargetToken) {
_transferProceeds(token, feeAmount);
continue;
}

if (token == _targetToken) {
// if _finalTargetToken is not set, directly transfer the fees to the transfer address
if (Token.unwrap(_finalTargetToken) == address(0)) {
// safe due to nonReentrant modifier (forwards all gas fees in case of the native token)
_targetToken.unsafeTransfer(_transferAddress, feeAmount);
// increment totalCollected amount
_totalCollected += feeAmount;
_transferProceeds(_targetToken, feeAmount);
} else if (
!_tradingEnabled(token) ||
_amountAvailableForTrading(token) < _minTokenSaleAmounts[token] ||
Expand Down Expand Up @@ -649,10 +664,7 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,

// if no final target token is defined, transfer the target token to `transferAddress`
if (Token.unwrap(_finalTargetToken) == address(0)) {
// safe due to nonreenrant modifier (forwards all available gas if token is native)
_targetToken.unsafeTransfer(_transferAddress, sourceAmount);
// increment total collected in `transferAddress`
_totalCollected += sourceAmount;
_transferProceeds(_targetToken, sourceAmount);
}

// if remaining balance is below the min token sale amount, reset the auction
Expand Down Expand Up @@ -687,34 +699,26 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
if (sourceAmount > maxInput) {
revert GreaterThanMaxInput();
}

// revert if unnecessary native token is received
if (_finalTargetToken != NATIVE_TOKEN && msg.value > 0) {
revert UnnecessaryNativeTokenReceived();
}
// check enough final target token (if final target token is native) has been sent for the trade
if (_finalTargetToken == NATIVE_TOKEN) {
if (msg.value < sourceAmount) {
revert InsufficientNativeTokenSent();
}
payable(_transferAddress).sendValue(sourceAmount);
} else {
// revert if unnecessary native token is received
if (msg.value > 0) {
revert UnnecessaryNativeTokenReceived();
}
// transfer the tokens from the user to the _transferAddress
_finalTargetToken.safeTransferFrom(msg.sender, _transferAddress, sourceAmount);
if (_finalTargetToken == NATIVE_TOKEN && msg.value < sourceAmount) {
revert InsufficientNativeTokenSent();
}

_finalTargetToken.safeTransferFrom(msg.sender, address(this), sourceAmount);
// transfer the _targetToken to the user
// safe due to nonReentrant modifier (forwards all available gas if native)
_targetToken.unsafeTransfer(msg.sender, targetAmount);

_transferProceeds(_finalTargetToken, sourceAmount);

// if final target token is native, refund any excess native token to caller
if (_finalTargetToken == NATIVE_TOKEN && msg.value > sourceAmount) {
payable(msg.sender).sendValue(msg.value - sourceAmount);
}

// increment total collected in _transferAddress
_totalCollected += sourceAmount;

// update the available target token sale amount
_targetTokenSaleAmount.current -= targetAmount;

Expand Down Expand Up @@ -905,6 +909,22 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
emit PairDisabledStatusUpdated(token, prevPairStatus, disabled);
}

function _setTransferAddress(address newTransferAddress) private {
address prevTransferAddress = _transferAddress;

// return if the transfer address is the same
if (prevTransferAddress == newTransferAddress) {
return;
}

_transferAddress = payable(newTransferAddress);

emit TransferAddressUpdated({
prevTransferAddress: prevTransferAddress,
newTransferAddress: newTransferAddress
});
}

/**
* @dev returns true if the auction price is below or equal to the minimum possible price
* @dev check if timeElapsed / priceDecayHalfLife >= 128
Expand Down Expand Up @@ -1012,6 +1032,17 @@ contract CarbonVortex is ICarbonVortex, Upgradeable, ReentrancyGuardUpgradeable,
return price;
}

function _transferProceeds(Token token, uint256 amount) private {
// increment totalCollected amount
_totalCollected += amount;
// if transfer address is 0, proceeds stay in the vortex
if (_transferAddress == address(0)) {
lbeder marked this conversation as resolved.
Show resolved Hide resolved
return;
}
// safe due to nonReentrant modifier (forwards all available gas in case of ETH)
token.unsafeTransfer(_transferAddress, amount);
}

function uncheckedInc(uint256 i) private pure returns (uint256 j) {
unchecked {
j = i + 1;
Expand Down
10 changes: 10 additions & 0 deletions contracts/vortex/interfaces/ICarbonVortex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ interface ICarbonVortex is IUpgradeable {
*/
event MinTokenSaleAmountUpdated(Token indexed token, uint128 prevMinTokenSaleAmount, uint128 newMinTokenSaleAmount);

/**
* @notice triggered when the transfer address is updated
*/
event TransferAddressUpdated(address indexed prevTransferAddress, address indexed newTransferAddress);

/**
* @notice returns the rewards ppm
*/
Expand Down Expand Up @@ -193,6 +198,11 @@ interface ICarbonVortex is IUpgradeable {
*/
function finalTargetToken() external view returns (Token);

/**
* @notice returns the transfer address
*/
function transferAddress() external view returns (address);

/**
* @notice trades *targetToken* for *targetAmount* of *token* based on the current token price (trade by target amount)
* @notice if token == *targetToken*, trades *finalTargetToken* for amount of *targetToken* and also
Expand Down
3 changes: 2 additions & 1 deletion deploy/tests/mainnet/0004-fee-burner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CarbonController, CarbonVortex, ProxyAdmin } from '../../../components/Contracts';
import { DeployedContracts, describeDeployment } from '../../../utils/Deploy';
import { ZERO_ADDRESS } from '../../../utils/Constants';
import { expect } from 'chai';
import { ethers } from 'hardhat';

Expand Down Expand Up @@ -33,7 +34,7 @@ describeDeployment(__filename, () => {
const implementationAddress = await proxyAdmin.getProxyImplementation(carbonVortex.address);
const carbonVortexImpl: CarbonVortex = await ethers.getContractAt('CarbonVortex', implementationAddress);
// hardcoding gas limit to avoid gas estimation attempts (which get rejected instead of reverted)
const tx = await carbonVortexImpl.initialize({ gasLimit: 6000000 });
const tx = await carbonVortexImpl.initialize(ZERO_ADDRESS, { gasLimit: 6000000 });
await expect(tx.wait()).to.be.reverted;
});
});
3 changes: 2 additions & 1 deletion deploy/tests/mainnet/0006-carbon-vortex-upgrade.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ZERO_ADDRESS } from '../../../utils/Constants';
import { CarbonController, CarbonVortex, ProxyAdmin } from '../../../components/Contracts';
import { DeployedContracts, describeDeployment } from '../../../utils/Deploy';
import { expect } from 'chai';
Expand Down Expand Up @@ -38,7 +39,7 @@ describeDeployment(__filename, () => {
const implementationAddress = await proxyAdmin.getProxyImplementation(carbonVortex.address);
const carbonVortexImpl: CarbonVortex = await ethers.getContractAt('CarbonVortex', implementationAddress);
// hardcoding gas limit to avoid gas estimation attempts (which get rejected instead of reverted)
const tx = await carbonVortexImpl.initialize({ gasLimit: 6000000 });
const tx = await carbonVortexImpl.initialize(ZERO_ADDRESS, { gasLimit: 6000000 });
await expect(tx.wait()).to.be.reverted;
});
});
3 changes: 2 additions & 1 deletion deploy/tests/mainnet/0012-carbon-vortex-upgrade.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CarbonController, CarbonVortex, ProxyAdmin } from '../../../components/Contracts';
import { DeployedContracts, describeDeployment } from '../../../utils/Deploy';
import { ZERO_ADDRESS } from '../../../utils/Constants';
import { expect } from 'chai';
import { ethers } from 'hardhat';

Expand Down Expand Up @@ -38,7 +39,7 @@ describeDeployment(__filename, () => {
const implementationAddress = await proxyAdmin.getProxyImplementation(carbonVortex.address);
const carbonVortexImpl: CarbonVortex = await ethers.getContractAt('CarbonVortex', implementationAddress);
// hardcoding gas limit to avoid gas estimation attempts (which get rejected instead of reverted)
const tx = await carbonVortexImpl.initialize({ gasLimit: 6000000 });
const tx = await carbonVortexImpl.initialize(ZERO_ADDRESS, { gasLimit: 6000000 });
await expect(tx.wait()).to.be.reverted;
});
});
3 changes: 2 additions & 1 deletion deploy/tests/mainnet/0016-carbon-vortex-upgrade.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CarbonVortex, ProxyAdmin } from '../../../components/Contracts';
import { DeployedContracts, describeDeployment } from '../../../utils/Deploy';
import { ZERO_ADDRESS } from '../../../utils/Constants';
import { expect } from 'chai';
import { ethers } from 'hardhat';

Expand All @@ -21,7 +22,7 @@ describeDeployment(__filename, () => {
const implementationAddress = await proxyAdmin.getProxyImplementation(carbonVortex.address);
const carbonControllerImpl: CarbonVortex = await ethers.getContractAt('CarbonVortex', implementationAddress);
// hardcoding gas limit to avoid gas estimation attempts (which get rejected instead of reverted)
const tx = await carbonControllerImpl.initialize({ gasLimit: 6000000 });
const tx = await carbonControllerImpl.initialize(ZERO_ADDRESS, { gasLimit: 6000000 });
await expect(tx.wait()).to.be.reverted;
});

Expand Down
3 changes: 2 additions & 1 deletion deploy/tests/mainnet/0017-carbon-vortex-upgrade.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CarbonVortex, ProxyAdmin } from '../../../components/Contracts';
import { DeployedContracts, describeDeployment } from '../../../utils/Deploy';
import { ZERO_ADDRESS } from '../../../utils/Constants';
import { expect } from 'chai';
import { ethers } from 'hardhat';

Expand All @@ -21,7 +22,7 @@ describeDeployment(__filename, () => {
const implementationAddress = await proxyAdmin.getProxyImplementation(carbonVortex.address);
const carbonControllerImpl: CarbonVortex = await ethers.getContractAt('CarbonVortex', implementationAddress);
// hardcoding gas limit to avoid gas estimation attempts (which get rejected instead of reverted)
const tx = await carbonControllerImpl.initialize({ gasLimit: 6000000 });
const tx = await carbonControllerImpl.initialize(ZERO_ADDRESS, { gasLimit: 6000000 });
await expect(tx.wait()).to.be.reverted;
});

Expand Down
Loading
Loading