Platform: Code4rena
Start Date: 05/05/2022
Pot Size: $125,000 DAI
Total HM: 17
Participants: 62
Period: 14 days
Judge: leastwood
Total Solo HM: 15
Id: 120
League: ETH
Rank: 12/62
Findings: 2
Award: $2,618.57
🌟 Selected for report: 2
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xkatana, 0xsomeone, AuditsAreUS, BouSalman, BowTiedWardens, Cityscape, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Picodes, Ruhum, TerrierLover, WatchPug, Waze, bobirichman, catchup, cccz, cryptphi, csanuragjain, delfin454000, ellahi, fatherOfBlocks, hake, horsefacts, hyh, jayjonah8, joestakey, kebabsec, kenta, mics, oyc_109, robee, samruna, shenwilly, sikorico, simon135, throttle, tintin
1745.7128 DAI - $1,745.71
Issue | Instances | |
---|---|---|
1 | Latent funds can be stolen | 1 |
2 | Low level calls don't check for contract existence | 1 |
3 | Set sane maximums for input parameters | 2 |
4 | Behavior described by comment is incomplete | 1 |
5 | Unsafe use of transfer() /transferFrom() with IERC20 | 4 |
6 | Return values of transfer() /transferFrom() not checked | 2 |
7 | Unused/empty receive() function | 2 |
8 | safeApprove() is deprecated | 32 |
9 | Missing checks for address(0x0) when assigning values to address state variables | 24 |
10 | abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256() | 1 |
11 | Upgradeable contract is missing a __gap[50] storage variable to allow for new storage variables in later versions | 3 |
Total: 73 instances over 11 issues
Issue | Instances | |
---|---|---|
1 | Adding a return statement when the function defines a named return variable, is redundant | 4 |
2 | override function arguments that are unused should have the variable name removed or commented out to avoid compiler warnings | 1 |
3 | public functions not called by the contract should be declared external instead | 12 |
4 | 2**<n> - 1 should be re-written as type(uint<n>).max | 1 |
5 | constant s should be defined rather than using magic numbers | 20 |
6 | Redundant cast | 4 |
7 | Numeric values having to do with time should use time units for readability | 1 |
8 | Missing event for critical parameter change | 3 |
9 | Use a more recent version of solidity | 12 |
10 | Use a more recent version of solidity | 1 |
11 | Use scientific notation (e.g. 1e18 ) rather than exponentiation (e.g. 10**18 ) | 2 |
12 | Inconsistent spacing in comments | 11 |
13 | Non-library/interface files should use fixed compiler versions, not floating ones | 16 |
14 | Typos | 12 |
15 | File does not contain an SPDX Identifier | 32 |
16 | File is missing NatSpec | 27 |
17 | NatSpec is incomplete | 17 |
18 | Event is missing indexed fields | 111 |
19 | Use allowlist/denylist rather than blacklist/whitelist | 1 |
Total: 288 instances over 19 issues
If someone manages, through either a bug or a mistake (self-destructing and sending funds to the contract), another user can claim the funds as their own. Measure the balance before and after, and use the difference, rather than measuring the total balance of the contract
There is 1 instance of this issue:
File: contracts-full/WETHGateway.sol #1 70 IAlchemistV2(alchemist).withdrawUnderlyingFrom(msg.sender, yieldToken, shares, address(this), minimumAmountOut); 71 72 uint256 amount = WETH.balanceOf(address(this)); 73 WETH.withdraw(amount); 74 75: (bool success, ) = recipient.call{value: amount}(new bytes(0));
Low level calls return success if called on a destructed contract. See OpenZeppelin's Address.so which checks address.code.length
There is 1 instance of this issue:
File: contracts-full/libraries/TokenUtils.sol #1 65 function safeTransfer(address token, address recipient, uint256 amount) internal { 66 (bool success, bytes memory data) = token.call( 67 abi.encodeWithSelector(IERC20Minimal.transfer.selector, recipient, amount) 68: );
There should be an upper limit to reasonable fees
There are 2 instances of this issue:
File: contracts-full/AlchemicTokenV2Base.sol #1 98 function setFlashFee(uint256 newFee) external onlyAdmin { 99 flashMintFee = newFee; 100 emit SetFlashMintFee(flashMintFee); 101: }
File: contracts-full/AlchemicTokenV2.sol #2 92 function setFlashFee(uint256 newFee) external onlyAdmin { 93 flashMintFee = newFee; 94 emit SetFlashMintFee(flashMintFee); 95: }
The event is not emitted when the fee is updated the first time (in the constructor)
There is 1 instance of this issue:
File: contracts-full/AlchemicTokenV2.sol #1 50 /// @notice An event which is emitted when the flash mint fee is updated. 51 /// 52 /// @param fee The new flash mint fee. 53 event SetFlashMintFee(uint256 fee); 54 55 constructor(string memory _name, string memory _symbol, uint256 _flashFee) ERC20(_name, _symbol) { 56 _setupRole(ADMIN_ROLE, msg.sender); 57 _setupRole(SENTINEL_ROLE, msg.sender); 58 _setRoleAdmin(SENTINEL_ROLE, ADMIN_ROLE); 59 _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); 60 flashMintFee = _flashFee; 61: }
transfer()
/transferFrom()
with IERC20
Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example Tether (USDT)'s transfer()
and transferFrom()
functions do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20
, their function signatures do not match and therefore the calls made, revert. Use OpenZeppelin’s SafeERC20
's safeTransfer()
/safeTransferFrom()
instead
There are 4 instances of this issue:
File: contracts-full/AutoleverageCurveMetapool.sol #1 16: IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial);
File: contracts-full/AutoleverageCurveFactoryethpool.sol #2 26: IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial);
File: contracts-full/gALCX.sol #3 89: bool success = alcx.transferFrom(msg.sender, address(this), amount);
File: contracts-full/gALCX.sol #4 106: bool success = alcx.transfer(msg.sender, amount); // Should return true or revert, but doesn't hurt
transfer()
/transferFrom()
not checkedNot all IERC20
implementations revert()
when there's a failure in transfer()
/transferFrom()
. The function signature has a boolean
return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually making a payment
There are 2 instances of this issue:
File: contracts-full/AutoleverageCurveMetapool.sol #1 16: IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial);
File: contracts-full/AutoleverageCurveFactoryethpool.sol #2 26: IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial);
receive()
functionIf the intention is for the Ether to be used, the function should call another function, otherwise it should revert
There are 2 instances of this issue:
File: contracts-full/AutoleverageCurveFactoryethpool.sol #1 17: receive() external payable {}
File: contracts-full/EthAssetManager.sol #2 228: receive() external payable { }
safeApprove()
is deprecatedDeprecated in favor of safeIncreaseAllowance()
and safeDecreaseAllowance()
. If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance()
can be used instead
There are 32 instances of this issue:
File: contracts-full/TransmuterBuffer.sol #1 236: TokenUtils.safeApprove(registeredUnderlyings[i], alchemist, 0);
File: contracts-full/TransmuterBuffer.sol #2 238: TokenUtils.safeApprove(debtToken, alchemist, 0);
File: contracts-full/TransmuterBuffer.sol #3 243: TokenUtils.safeApprove(registeredUnderlyings[i], alchemist, type(uint256).max);
File: contracts-full/TransmuterBuffer.sol #4 245: TokenUtils.safeApprove(debtToken, alchemist, type(uint256).max);
File: contracts-full/TransmuterBuffer.sol #5 284: TokenUtils.safeApprove(underlyingToken, alchemist, type(uint256).max);
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #6 105: SafeERC20.safeApprove(parentToken, address(token), mintedStEth);
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #7 129: SafeERC20.safeApprove(parentToken, curvePool, unwrappedStEth);
File: contracts-full/adapters/vesper/VesperAdapterV1.sol #8 62: SafeERC20.safeApprove(underlyingToken, token, amount);
File: contracts-full/adapters/fuse/FuseTokenAdapterV1.sol #9 71: SafeERC20.safeApprove(underlyingToken, token, amount);
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol #10 32: TokenUtils.safeApprove(underlyingToken, token, amount);
File: contracts-full/ThreePoolAssetManager.sol #11 782: SafeERC20.safeApprove(address(tokens[i]), address(threePool), 0);
File: contracts-full/ThreePoolAssetManager.sol #12 783: SafeERC20.safeApprove(address(tokens[i]), address(threePool), amounts[i]);
File: contracts-full/ThreePoolAssetManager.sol #13 838: SafeERC20.safeApprove(address(token), address(threePool), 0);
File: contracts-full/ThreePoolAssetManager.sol #14 839: SafeERC20.safeApprove(address(token), address(threePool), amount);
File: contracts-full/ThreePoolAssetManager.sol #15 879: SafeERC20.safeApprove(address(threePoolToken), address(threePool), 0);
File: contracts-full/ThreePoolAssetManager.sol #16 880: SafeERC20.safeApprove(address(threePoolToken), address(threePool), amount);
File: contracts-full/ThreePoolAssetManager.sol #17 908: SafeERC20.safeApprove(address(tokens[i]), address(metaPool), 0);
File: contracts-full/ThreePoolAssetManager.sol #18 909: SafeERC20.safeApprove(address(tokens[i]), address(metaPool), amounts[i]);
File: contracts-full/ThreePoolAssetManager.sol #19 944: SafeERC20.safeApprove(address(token), address(metaPool), 0);
File: contracts-full/ThreePoolAssetManager.sol #20 945: SafeERC20.safeApprove(address(token), address(metaPool), amount);
File: contracts-full/ThreePoolAssetManager.sol #21 987: SafeERC20.safeApprove(address(metaPool), address(convexBooster), 0);
File: contracts-full/ThreePoolAssetManager.sol #22 988: SafeERC20.safeApprove(address(metaPool), address(convexBooster), amount);
File: contracts-full/EthAssetManager.sol #23 576: SafeERC20.safeApprove(address(tokens[i]), address(metaPool), 0);
File: contracts-full/EthAssetManager.sol #24 577: SafeERC20.safeApprove(address(tokens[i]), address(metaPool), amounts[i]);
File: contracts-full/EthAssetManager.sol #25 620: SafeERC20.safeApprove(address(token), address(metaPool), 0);
File: contracts-full/EthAssetManager.sol #26 621: SafeERC20.safeApprove(address(token), address(metaPool), amount);
File: contracts-full/EthAssetManager.sol #27 671: SafeERC20.safeApprove(address(metaPool), address(convexBooster), 0);
File: contracts-full/EthAssetManager.sol #28 672: SafeERC20.safeApprove(address(metaPool), address(convexBooster), amount);
File: contracts-full/AlchemistV2.sol #29 382: TokenUtils.safeApprove(yieldToken, config.adapter, type(uint256).max);
File: contracts-full/AlchemistV2.sol #30 383: TokenUtils.safeApprove(adapter.underlyingToken(), config.adapter, type(uint256).max);
File: contracts-full/AlchemistV2.sol #31 478: TokenUtils.safeApprove(yieldToken, adapter, type(uint256).max);
File: contracts-full/AlchemistV2.sol #32 479: TokenUtils.safeApprove(ITokenAdapter(adapter).underlyingToken(), adapter, type(uint256).max);
address(0x0)
when assigning values to address
state variablesThere are 24 instances of this issue:
File: contracts-full/TransmuterBuffer.sol #1 88: debtToken = _debtToken;
File: contracts-full/TransmuterBuffer.sol #2 241: alchemist = _alchemist;
File: contracts-full/StakingPools.sol #3 134: governance = _pendingGovernance;
File: contracts-full/TransmuterV2.sol #4 153: syntheticToken = _syntheticToken;
File: contracts-full/TransmuterV2.sol #5 154: underlyingToken = _underlyingToken;
File: contracts-full/TransmuterV2.sol #6 158: buffer = _buffer;
File: contracts-full/TransmuterV2.sol #7 163: whitelist = _whitelist;
File: contracts-full/TransmuterV2.sol #8 198: buffer = _newCollateralSource;
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol #9 20: token = _token;
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol #10 21: underlyingToken = _underlyingToken;
File: contracts-full/gALCX.sol #11 40: owner = _owner;
File: contracts-full/ThreePoolAssetManager.sol #12 446: pendingAdmin = value;
File: contracts-full/ThreePoolAssetManager.sol #13 477: operator = value;
File: contracts-full/ThreePoolAssetManager.sol #14 485: rewardReceiver = value;
File: contracts-full/ThreePoolAssetManager.sol #15 493: transmuterBuffer = value;
File: contracts-full/WETHGateway.sol #16 24: whitelist = _whitelist;
File: contracts-full/TransmuterConduit.sol #17 22: token = _token;
File: contracts-full/TransmuterConduit.sol #18 23: sourceTransmuter = _source;
File: contracts-full/TransmuterConduit.sol #19 24: sinkTransmuter = _sink;
File: contracts-full/EthAssetManager.sol #20 294: pendingAdmin = value;
File: contracts-full/EthAssetManager.sol #21 325: operator = value;
File: contracts-full/EthAssetManager.sol #22 333: rewardReceiver = value;
File: contracts-full/EthAssetManager.sol #23 341: transmuterBuffer = value;
File: contracts-full/AlchemistV2.sol #24 283: pendingAdmin = value;
abi.encodePacked()
should not be used with dynamic types when passing the result to a hash function such as keccak256()
Use abi.encode()
instead which will pad items to 32 bytes, which will prevent hash collisions (e.g. abi.encodePacked(0x123,0x456)
=> 0x123456
=> abi.encodePacked(0x1,0x23456)
, but abi.encode(0x123,0x456)
=> 0x0...1230...456
). "Unless there is a compelling reason, abi.encode
should be preferred". If there is only one argument to abi.encodePacked()
it can often be cast to bytes()
or bytes32()
instead.
There is 1 instance of this issue:
File: contracts-full/libraries/RocketPool.sol #1 14: keccak256(abi.encodePacked("contract.address", "rocketTokenRETH"))
__gap[50]
storage variable to allow for new storage variables in later versionsSee this link for a description of this storage variable. While some contracts may not currently be sub-classed, adding the variable now protects against forgetting to add it in the future.
There are 3 instances of this issue:
File: contracts-full/AlchemicTokenV2Base.sol #1 20: contract AlchemicTokenV2Base is ERC20Upgradeable, AccessControlUpgradeable, IERC3156FlashLender, ReentrancyGuardUpgradeable {
File: contracts-full/TransmuterV2.sol #2 26: contract TransmuterV2 is ITransmuterV2, Initializable, ReentrancyGuardUpgradeable, AccessControlUpgradeable {
File: contracts-full/CrossChainCanonicalBase.sol #3 12: contract CrossChainCanonicalBase is ERC20PermitUpgradeable, ReentrancyGuardUpgradeable, OwnableUpgradeable {
return
statement when the function defines a named return variable, is redundantThere are 4 instances of this issue:
File: contracts-full/TransmuterV2.sol #1 366: return unexchangedBalance;
File: contracts-full/TransmuterV2.sol #2 560: return exchangedBalance;
File: contracts-full/TransmuterV2.sol #3 572: return exchangedBalance;
File: contracts-full/EthAssetManager.sol #4 529: return result;
override
function arguments that are unused should have the variable name removed or commented out to avoid compiler warningsThere is 1 instance of this issue:
File: contracts-full/AutoleverageCurveMetapool.sol #1 20: function _maybeConvertCurveOutput(uint256 amountOut) internal override {}
public
functions not called by the contract should be declared external
insteadContracts are allowed to override their parents' functions and change the visibility from external
to public
.
There are 12 instances of this issue:
File: contracts-full/CrossChainCanonicalAlchemicTokenV2.sol #1 8 function initialize( 9 string memory name, 10 string memory symbol, 11 address[] memory _bridgeTokens 12: ) public initializer {
File: contracts-full/AlchemicTokenV1.sol #2 138: function burn(uint256 amount) public {
File: contracts-full/AlchemicTokenV1.sol #3 148: function burnFrom(address owner, uint256 amount) public {
File: contracts-full/AlchemicTokenV1.sol #4 159: function lowerHasMinted(uint256 amount) public onlyWhitelisted {
File: contracts-full/CrossChainCanonicalGALCX.sol #5 7 function initialize( 8 string memory name, 9 string memory symbol, 10 address[] memory _bridgeTokens 11: ) public initializer {
File: contracts-full/ThreePoolAssetManager.sol #6 298: function exchangeRate(ThreePoolAsset asset) public view returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #7 330 function calculateRebalance( 331 MetaPoolAsset rebalanceAsset, 332 ThreePoolAsset targetExchangeAsset, 333 uint256 targetExchangeRate 334: ) public view returns (uint256 delta, bool add) {
File: contracts-full/ThreePoolAssetManager.sol #8 408: function claimableRewards() public view returns (uint256 amountCurve, uint256 amountConvex) {
File: contracts-full/ThreePoolAssetManager.sol #9 717: function reclaimThreePoolAsset(ThreePoolAsset asset, uint256 amount) public lock onlyAdmin {
File: contracts-full/EthAssetManager.sol #10 253: function exchangeRate() public view returns (uint256) {
File: contracts-full/EthAssetManager.sol #11 269: function claimableRewards() public view returns (uint256 amountCurve, uint256 amountConvex) {
File: contracts-full/EthAssetManager.sol #12 494: function reclaimEth(uint256 amount) public lock onlyAdmin {
2**<n> - 1
should be re-written as type(uint<n>).max
Earlier versions of solidity can use uint<n>(-1)
instead. Expressions not including the - 1
can often be re-written to accomodate the change (e.g. by using a >
rather than a >=
, which will also save some gas)
There is 1 instance of this issue:
File: contracts-full/libraries/SafeCast.sol #1 13: if (y >= 2**255) {
constant
s should be defined rather than using magic numbersThere are 20 instances of this issue:
File: contracts-full/TransmuterBuffer.sol #1 /// @audit 100 520: uint256 minimumAmountOut = amountUnderlying - amountUnderlying * 100 / 10000;
File: contracts-full/TransmuterBuffer.sol #2 /// @audit 10000 520: uint256 minimumAmountOut = amountUnderlying - amountUnderlying * 100 / 10000;
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #3 /// @audit 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE 53: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
File: contracts-full/gALCX.sol #4 /// @audit 18 25: constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol, 18) {
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #5 /// @audit 3 6: uint256 constant N_COINS = 3;
File: contracts-full/ThreePoolAssetManager.sol #6 /// @audit 1e4 47: uint256 constant SLIPPAGE_PRECISION = 1e4;
File: contracts-full/ThreePoolAssetManager.sol #7 /// @audit 1e18 50: uint256 constant CURVE_PRECISION = 1e18;
File: contracts-full/ThreePoolAssetManager.sol #8 /// @audit 256 353: for (uint256 i = 0; i < 256; i++) {
File: contracts-full/libraries/SafeERC20.sol #9 /// @audit 32 34: if (!success || data.length < 32) {
File: contracts-full/libraries/LiquidityMath.sol #10 /// @audit 18 41: return (input * (10**18)) / (10**decimals);
File: contracts-full/libraries/LiquidityMath.sol #11 /// @audit 18 46: return (input * (10**decimals)) / (10**18);
File: contracts-full/libraries/SafeCast.sol #12 /// @audit 255 13: if (y >= 2**255) {
File: contracts-full/libraries/TokenUtils.sol #13 /// @audit 32 31: if (!success || data.length < 32) {
File: contracts-full/libraries/TokenUtils.sol #14 /// @audit 32 51: if (!success || data.length < 32) {
File: contracts-full/libraries/LibFuse.sol #15 /// @audit 0.0005e16 38: require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");
File: contracts-full/CrossChainCanonicalBase.sol #16 /// @audit 400 65: swapFees[_bridgeTokens[i]] = [400, 400];
File: contracts-full/CrossChainCanonicalBase.sol #17 /// @audit 400 65: swapFees[_bridgeTokens[i]] = [400, 400];
File: contracts-full/EthAssetManager.sol #18 /// @audit 1e4 41: uint256 constant SLIPPAGE_PRECISION = 1e4;
File: contracts-full/EthAssetManager.sol #19 /// @audit 1e18 44: uint256 constant CURVE_PRECISION = 1e18;
File: contracts-full/EthAssetManager.sol #20 /// @audit 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE 216: if (_metaPoolAssetCache[i] == IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) {
The type of the variable is the same as the type to which the variable is being cast
There are 4 instances of this issue:
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #1 105: SafeERC20.safeApprove(parentToken, address(token), mintedStEth);
File: contracts-full/ThreePoolAssetManager.sol #2 731: SafeERC20.safeTransfer(address(token), msg.sender, amount);
File: contracts-full/CrossChainCanonicalBase.sol #3 182: TokenUtils.safeTransfer(address(tokenAddress), msg.sender, tokenAmount);
File: contracts-full/EthAssetManager.sol #4 510: SafeERC20.safeTransfer(address(token), msg.sender, amount);
There are units for seconds, minutes, hours, days, and weeks
There is 1 instance of this issue:
File: contracts-full/libraries/Limiters.sol #1 12: uint256 constant public MAX_COOLDOWN_BLOCKS = 7200;
There are 3 instances of this issue:
File: contracts-full/AlchemicTokenV2Base.sol #1 196 function setMaxFlashLoan(uint _maxFlashLoanAmount) external onlyAdmin { 197 maxFlashLoanAmount = _maxFlashLoanAmount; 198: }
File: contracts-full/TransmuterV2.sol #2 196 function setCollateralSource(address _newCollateralSource) external { 197 _onlyAdmin(); 198 buffer = _newCollateralSource; 199: }
File: contracts-full/AlchemicTokenV2.sol #3 164 function setMaxFlashLoan(uint _maxFlashLoanAmount) external onlyAdmin { 165 maxFlashLoanAmount = _maxFlashLoanAmount; 166: }
Use a solidity version of at least 0.8.13 to get the ability to use using for
with a list of free functions
There are 12 instances of this issue:
File: contracts-full/TransmuterBuffer.sol #1 2: pragma solidity ^0.8.11;
File: contracts-full/StakingPools.sol #2 2: pragma solidity ^0.8.11;
File: contracts-full/utils/Whitelist.sol #3 1: pragma solidity ^0.8.11;
File: contracts-full/AlchemicTokenV1.sol #4 2: pragma solidity ^0.8.11;
File: contracts-full/TransmuterV2.sol #5 2: pragma solidity ^0.8.11;
File: contracts-full/libraries/LiquidityMath.sol #6 2: pragma solidity >=0.5.0;
File: contracts-full/libraries/Sets.sol #7 1: pragma solidity ^0.8.11;
File: contracts-full/libraries/Limiters.sol #8 1: pragma solidity ^0.8.11;
File: contracts-full/libraries/Tick.sol #9 2: pragma solidity >=0.5.0;
File: contracts-full/libraries/pools/Pool.sol #10 2: pragma solidity ^0.8.11;
File: contracts-full/libraries/pools/Stake.sol #11 2: pragma solidity ^0.8.11;
File: contracts-full/AlchemistV2.sol #12 1: pragma solidity ^0.8.11;
Use a solidity version of at least 0.8.4 to get bytes.concat()
instead of abi.encodePacked(<bytes>,<bytes>)
Use a solidity version of at least 0.8.12 to get string.concat()
instead of abi.encodePacked(<str>,<str>)
There is 1 instance of this issue:
File: contracts-full/libraries/RocketPool.sol #1 1: pragma solidity >=0.5.0;
1e18
) rather than exponentiation (e.g. 10**18
)There are 2 instances of this issue:
File: contracts-full/libraries/LiquidityMath.sol #1 41: return (input * (10**18)) / (10**decimals);
File: contracts-full/libraries/LiquidityMath.sol #2 46: return (input * (10**decimals)) / (10**18);
Some lines use // x
and some use //x
. The instances below point out the usages that don't follow the majority, within each file
There are 11 instances of this issue:
File: contracts-full/interfaces/IAaveLendingPool.sol #1 4: // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
File: contracts-full/interfaces/external/aave/DataTypes.sol #2 6: // Stores the reserve configuration.
File: contracts-full/interfaces/external/aave/DataTypes.sol #3 8: // The liquidity index. Expressed in ray.
File: contracts-full/interfaces/external/aave/DataTypes.sol #4 10: // Variable borrow index. Expressed in ray.
File: contracts-full/interfaces/external/aave/DataTypes.sol #5 12: // The current supply rate. Expressed in ray.
File: contracts-full/interfaces/external/aave/DataTypes.sol #6 14: // The current variable borrow rate. Expressed in ray.
File: contracts-full/interfaces/external/aave/DataTypes.sol #7 16: // The current stable borrow rate. Expressed in ray.
File: contracts-full/interfaces/external/aave/DataTypes.sol #8 19: // Tokens addresses.
File: contracts-full/interfaces/external/aave/DataTypes.sol #9 23: // Address of the interest rate strategy.
File: contracts-full/interfaces/external/aave/DataTypes.sol #10 25: // The id of the reserve. Represents the position in the list of the active reserves.
File: contracts-full/libraries/pools/Pool.sol #11 102: ///ck
There are 16 instances of this issue:
File: contracts-full/AutoleverageCurveMetapool.sol #1 2: pragma solidity ^0.8.11;
File: contracts-full/AlchemicTokenV2Base.sol #2 2: pragma solidity ^0.8.11;
File: contracts-full/TransmuterBuffer.sol #3 2: pragma solidity ^0.8.11;
File: contracts-full/StakingPools.sol #4 2: pragma solidity ^0.8.11;
File: contracts-full/CrossChainCanonicalAlchemicTokenV2.sol #5 2: pragma solidity ^0.8.11;
File: contracts-full/utils/Whitelist.sol #6 1: pragma solidity ^0.8.11;
File: contracts-full/AutoleverageCurveFactoryethpool.sol #7 2: pragma solidity ^0.8.11;
File: contracts-full/AlchemicTokenV1.sol #8 2: pragma solidity ^0.8.11;
File: contracts-full/TransmuterV2.sol #9 2: pragma solidity ^0.8.11;
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol #10 1: pragma solidity ^0.8.11;
File: contracts-full/gALCX.sol #11 2: pragma solidity ^0.8.11;
File: contracts-full/AlchemicTokenV2.sol #12 2: pragma solidity ^0.8.11;
File: contracts-full/CrossChainCanonicalGALCX.sol #13 2: pragma solidity ^0.8.11;
File: contracts-full/CrossChainCanonicalBase.sol #14 2: pragma solidity ^0.8.11;
File: contracts-full/WETHGateway.sol #15 1: pragma solidity ^0.8.11;
File: contracts-full/AlchemistV2.sol #16 1: pragma solidity ^0.8.11;
There are 12 instances of this issue:
File: contracts-full/TransmuterV2.sol #1 /// @audit identitifer 101: /// @dev The identitifer of the sentinel role
File: contracts-full/interfaces/ICurveFactoryethpool.sol #2 /// @audit valie 7: /// @param j Index valie of the underlying coin to recieve
File: contracts-full/interfaces/ICurveFactoryethpool.sol #3 /// @audit recieve 7: /// @param j Index valie of the underlying coin to recieve
File: contracts-full/interfaces/ICurveMetapool.sol #4 /// @audit valie 7: /// @param j Index valie of the underlying coin to recieve
File: contracts-full/interfaces/ICurveMetapool.sol #5 /// @audit recieve 7: /// @param j Index valie of the underlying coin to recieve
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #6 /// @audit recieved 211: /// @param minimumAmountOut The minimum amount of underlying tokens needed to be recieved as a result of unwrapping the yield tokens.
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #7 /// @audit coversion 102: /// @return The coversion factor.
File: contracts-full/interfaces/ITransmuterBuffer.sol #8 /// @audit recieved 177: /// @param minimumAmountOut The minimum amount of underlying tokens needed to be recieved as a result of unwrapping the yield tokens.
File: contracts-full/ThreePoolAssetManager.sol #9 /// @audit underying 297: /// @return The amount of the underying.
File: contracts-full/libraries/Limiters.sol #10 /// @audit determins 29: /// @param blocks The number of blocks that determins the rate of the LGF.
File: contracts-full/libraries/Limiters.sol #11 /// @audit LFG 53: /// @param maximum The maximum value of the LFG.
File: contracts-full/libraries/pools/Pool.sol #12 /// @audit ck 102: ///ck
There are 32 instances of this issue:
File: contracts-full/utils/Whitelist.sol #1 0: pragma solidity ^0.8.11;
File: contracts-full/base/Errors.sol #2 0: pragma solidity ^0.8.11;
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol #3 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/IWhitelist.sol #4 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/IERC20Mintable.sol #5 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/ICurveFactoryethpool.sol #6 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/ICurveMetapool.sol #7 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/IAaveFlashLoanReceiver.sol #8 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/IWETH9.sol #9 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Burnable.sol #10 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IAaveLendingPool.sol #11 0: pragma solidity ^0.8.11;
File: contracts-full/interfaces/external/IWETH9.sol #12 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/tether/ITetherToken.sol #13 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IAlchemistV2.sol #14 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/ITokenAdapter.sol #15 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IWETHGateway.sol #16 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Minimal.sol #17 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20TokenReceiver.sol #18 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Actions.sol #19 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #20 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #21 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2AdminActions.sol #22 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Errors.sol #23 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Immutables.sol #24 0: pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Metadata.sol #25 0: pragma solidity >=0.5.0;
File: contracts-full/libraries/Sets.sol #26 0: pragma solidity ^0.8.11;
File: contracts-full/libraries/Limiters.sol #27 0: pragma solidity ^0.8.11;
File: contracts-full/libraries/RocketPool.sol #28 0: pragma solidity >=0.5.0;
File: contracts-full/libraries/TokenUtils.sol #29 0: pragma solidity ^0.8.11;
File: contracts-full/WETHGateway.sol #30 0: pragma solidity ^0.8.11;
File: contracts-full/TransmuterConduit.sol #31 0: pragma solidity 0.8.13;
File: contracts-full/AlchemistV2.sol #32 0: pragma solidity ^0.8.11;
There are 27 instances of this issue:
File: contracts-full/AutoleverageCurveMetapool.sol (various lines) #1
File: contracts-full/CrossChainCanonicalAlchemicTokenV2.sol (various lines) #2
File: contracts-full/adapters/yearn/YearnTokenAdapter.sol (various lines) #3
File: contracts-full/interfaces/lido/IWstETH.sol (various lines) #4
File: contracts-full/interfaces/lido/IStETH.sol (various lines) #5
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol (various lines) #6
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol (various lines) #7
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol (various lines) #8
File: contracts-full/interfaces/convex/IConvexToken.sol (various lines) #9
File: contracts-full/interfaces/convex/IConvexBooster.sol (various lines) #10
File: contracts-full/interfaces/convex/IConvexRewards.sol (various lines) #11
File: contracts-full/interfaces/IAaveLendingPool.sol (various lines) #12
File: contracts-full/interfaces/rocket/IRocketStorage.sol (various lines) #13
File: contracts-full/interfaces/rocket/IRETH.sol (various lines) #14
File: contracts-full/interfaces/external/aave/IWethGateway.sol (various lines) #15
File: contracts-full/interfaces/external/maker/IDssProxyActions.sol (various lines) #16
File: contracts-full/interfaces/external/IProxyAdmin.sol (various lines) #17
File: contracts-full/interfaces/IALCXSource.sol (various lines) #18
File: contracts-full/interfaces/ITransmuterV1.sol (various lines) #19
File: contracts-full/interfaces/IAlchemistV2.sol (various lines) #20
File: contracts-full/interfaces/vesper/IVesperRewards.sol (various lines) #21
File: contracts-full/interfaces/vesper/IVesperPool.sol (various lines) #22
File: contracts-full/interfaces/IStakingPools.sol (various lines) #23
File: contracts-full/interfaces/compound/ICERC20.sol (various lines) #24
File: contracts-full/interfaces/compound/IInterestRateModel.sol (various lines) #25
File: contracts-full/CrossChainCanonicalGALCX.sol (various lines) #26
File: contracts-full/CrossChainCanonicalBase.sol (various lines) #27
There are 17 instances of this issue:
File: contracts-full/TransmuterBuffer.sol #1 /// @audit Missing: '@return' 436 /// 437 /// @param yieldToken The address of the target yield token. 438 function _getTotalBuffered(address yieldToken) 439 internal 440 view 441: returns (uint256)
File: contracts-full/TransmuterBuffer.sol #2 /// @audit Missing: '@return' 452 /// 453 /// @param underlyingToken the underlying token whos flow is being updated 454: function _updateFlow(address underlyingToken) internal returns (uint256) {
File: contracts-full/libraries/Limiters.sol #3 /// @audit Missing: '@param _minLimit' 26 /// @dev Instantiates a new linear growth function. 27 /// 28 /// @param maximum The maximum value for the LGF. 29 /// @param blocks The number of blocks that determins the rate of the LGF. 30 /// 31 /// @return The LGF struct. 32: function createLinearGrowthLimiter(uint256 maximum, uint256 blocks, uint256 _minLimit) internal view returns (LinearGrowthLimiter memory) {
File: contracts-full/libraries/Limiters.sol #4 /// @audit Missing: '@param self' 90 /// @dev Get the current value of the linear growth limiter. 91 /// 92 /// @return The current value. 93: function get(LinearGrowthLimiter storage self) internal view returns (uint256) {
File: contracts-full/libraries/FixedPointMath.sol #5 /// @audit Missing: '@param self' 172 /** 173 * @notice Truncates a fixed point decimal into an unsigned 256-bit integer. 174 * 175 * @return The integer portion of the fixed point decimal. 176 */ 177: function truncate(Number memory self) internal pure returns (uint256) {
File: contracts-full/libraries/Tick.sol #6 /// @audit Missing: '@param self' 32 /// @dev Gets the next tick in the buffer. 33 /// 34 /// This increments the position in the buffer. 35 /// 36 /// @return The next tick. 37: function next(Tick.Cache storage self) internal returns (Tick.Info storage) {
File: contracts-full/libraries/Tick.sol #7 /// @audit Missing: '@param self' 42 /// @dev Gets the current tick being written to. 43 /// 44 /// @return The current tick. 45: function current(Tick.Cache storage self) internal view returns (Tick.Info storage) {
File: contracts-full/libraries/Tick.sol #8 /// @audit Missing: '@return' 51 /// @param self The reference to the buffer. 52 /// @param n The nth tick to get. 53: function get(Tick.Cache storage self, uint256 n) internal view returns (Tick.Info storage) {
File: contracts-full/libraries/pools/Pool.sol #9 /// @audit Missing: '@param _data' 34 /// @dev Updates the pool. 35 /// 36 /// @param _ctx the pool context. 37: function update(Data storage _data, Context storage _ctx) internal {
File: contracts-full/libraries/pools/Pool.sol #10 /// @audit Missing: '@param _data' 42 /// @dev Gets the rate at which the pool will distribute rewards to stakers. 43 /// 44 /// @param _ctx the pool context. 45 /// 46 /// @return the reward rate of the pool in tokens per block. 47 function getRewardRate(Data storage _data, Context storage _ctx) 48 internal view 49: returns (uint256)
File: contracts-full/libraries/pools/Pool.sol #11 /// @audit Missing: '@param _data' 54 /// @dev Gets the accumulated reward weight of a pool. 55 /// 56 /// @param _ctx the pool context. 57 /// 58 /// @return the accumulated reward weight. 59 function getUpdatedAccumulatedRewardWeight(Data storage _data, Context storage _ctx) 60 internal view 61: returns (FixedPointMath.Number memory)
File: contracts-full/libraries/pools/Pool.sol #12 /// @audit Missing: '@param _self' 83 /// @dev Adds an element to the list. 84 /// 85 /// @param _element the element to add. 86: function push(List storage _self, Data memory _element) internal {
File: contracts-full/libraries/pools/Pool.sol #13 /// @audit Missing: '@param _self' 90 /// @dev Gets an element from the list. 91 /// 92 /// @param _index the index in the list. 93 /// 94 /// @return the element at the specified index. 95: function get(List storage _self, uint256 _index) internal view returns (Data storage) {
File: contracts-full/libraries/pools/Pool.sol #14 /// @audit Missing: '@param _self' 99 /// @dev Gets the last element in the list. 100 /// 101 /// This function will revert if there are no elements in the list. 102 ///ck 103 /// @return the last element in the list. 104: function last(List storage _self) internal view returns (Data storage) {
File: contracts-full/libraries/pools/Pool.sol #15 /// @audit Missing: '@param _self' 108 /// @dev Gets the index of the last element in the list. 109 /// 110 /// This function will revert if there are no elements in the list. 111 /// 112 /// @return the index of the last element. 113: function lastIndex(List storage _self) internal view returns (uint256) {
File: contracts-full/libraries/pools/Pool.sol #16 /// @audit Missing: '@param _self' 117 /// @dev Gets the number of elements in the list. 118 /// 119 /// @return the number of elements. 120: function length(List storage _self) internal view returns (uint256) {
File: contracts-full/AlchemistV2.sol #17 /// @audit Missing: '@param recipient' 1328 /// @dev Unwraps `amount` of `yieldToken` into its underlying token. 1329 /// 1330 /// @param yieldToken The address of the yield token to unwrap. 1331 /// @param amount The amount of the underlying token to wrap. 1332 /// @param minimumAmountOut The minimum amount of underlying tokens that are expected to be received from the 1333 /// operation. 1334 /// 1335 /// @return The amount of underlying tokens that resulted from the operation. 1336 function _unwrap( 1337 address yieldToken, 1338 uint256 amount, 1339 address recipient, 1340 uint256 minimumAmountOut 1341: ) internal returns (uint256) {
indexed
fieldsEach event
should use three indexed
fields if there are three or more fields
There are 111 instances of this issue:
File: contracts-full/AlchemicTokenV2Base.sol #1 55: event Paused(address minter, bool state);
File: contracts-full/AlchemicTokenV2Base.sol #2 60: event SetFlashMintFee(uint256 fee);
File: contracts-full/StakingPools.sol #3 41 event PendingGovernanceUpdated( 42 address pendingGovernance 43: );
File: contracts-full/StakingPools.sol #4 45 event GovernanceUpdated( 46 address governance 47: );
File: contracts-full/StakingPools.sol #5 49 event RewardRateUpdated( 50 uint256 rewardRate 51: );
File: contracts-full/StakingPools.sol #6 53 event PoolRewardWeightUpdated( 54 uint256 indexed poolId, 55 uint256 rewardWeight 56: );
File: contracts-full/StakingPools.sol #7 63 event TokensDeposited( 64 address indexed user, 65 uint256 indexed poolId, 66 uint256 amount 67: );
File: contracts-full/StakingPools.sol #8 69 event TokensWithdrawn( 70 address indexed user, 71 uint256 indexed poolId, 72 uint256 amount 73: );
File: contracts-full/StakingPools.sol #9 75 event TokensClaimed( 76 address indexed user, 77 uint256 indexed poolId, 78 uint256 amount 79: );
File: contracts-full/AlchemicTokenV1.sol #10 19: event Paused(address minter, bool state);
File: contracts-full/gALCX.sol #11 19: event ExchangeRateChange(uint _exchangeRate);
File: contracts-full/gALCX.sol #12 20: event Stake(address _from, uint _gAmount, uint _amount);
File: contracts-full/gALCX.sol #13 21: event Unstake(address _from, uint _gAmount, uint _amount);
File: contracts-full/AlchemicTokenV2.sol #14 48: event Paused(address minter, bool state);
File: contracts-full/AlchemicTokenV2.sol #15 53: event SetFlashMintFee(uint256 fee);
File: contracts-full/interfaces/IWhitelist.sol #16 9: event AccountAdded(address account);
File: contracts-full/interfaces/IWhitelist.sol #17 14: event AccountRemoved(address account);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #18 35: event SetAlchemist(address alchemist);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #19 41: event SetAmo(address underlyingToken, address amo);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #20 47: event SetDivertToAmo(address underlyingToken, bool divert);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #21 53: event RegisterAsset(address underlyingToken, address transmuter);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #22 59: event SetFlowRate(address underlyingToken, uint256 flowRate);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #23 65: event SetSource(address source, bool flag);
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #24 68: event SetTransmuter(address underlyingToken, address transmuter);
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #25 10: event AdminUpdated(address admin);
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #26 15: event PendingAdminUpdated(address pendingAdmin);
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #27 20: event Paused(bool flag);
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #28 27 event Deposit( 28 address indexed sender, 29 address indexed owner, 30 uint256 amount 31: );
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #29 38 event Withdraw( 39 address indexed sender, 40 address indexed recipient, 41 uint256 amount 42: );
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #30 49 event Claim( 50 address indexed sender, 51 address indexed recipient, 52 uint256 amount 53: );
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #31 59 event Exchange( 60 address indexed sender, 61 uint256 amount 62: );
File: contracts-full/interfaces/external/aave/IAToken.sol #32 13: event Mint(address indexed from, uint256 value, uint256 index);
File: contracts-full/interfaces/external/aave/IAToken.sol #33 21: event Burn(address indexed from, address indexed target, uint256 value, uint256 index);
File: contracts-full/interfaces/external/aave/IAToken.sol #34 29: event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
File: contracts-full/interfaces/external/aave/ILendingPool.sol #35 65: event Swap(address indexed reserve, address indexed user, uint256 rateMode);
File: contracts-full/interfaces/external/aave/ILendingPool.sol #36 144 event ReserveDataUpdated( 145 address indexed reserve, 146 uint256 liquidityRate, 147 uint256 stableBorrowRate, 148 uint256 variableBorrowRate, 149 uint256 liquidityIndex, 150 uint256 variableBorrowIndex 151: );
File: contracts-full/interfaces/external/aave/ILendingPoolAddressesProvider.sol #37 12: event MarketIdSet(string newMarketId);
File: contracts-full/interfaces/external/aave/ILendingPoolAddressesProvider.sol #38 20: event ProxyCreated(bytes32 id, address indexed newAddress);
File: contracts-full/interfaces/external/aave/ILendingPoolAddressesProvider.sol #39 21: event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
File: contracts-full/interfaces/external/tether/ITetherToken.sol #40 29: event Issue(uint256 amount);
File: contracts-full/interfaces/external/tether/ITetherToken.sol #41 32: event Redeem(uint256 amount);
File: contracts-full/interfaces/external/tether/ITetherToken.sol #42 35: event Deprecate(address newAddress);
File: contracts-full/interfaces/external/tether/ITetherToken.sol #43 38: event Params(uint256 feeBasisPoints, uint256 maxFee);
File: contracts-full/interfaces/ITransmuterBuffer.sol #44 31: event SetAlchemist(address alchemist);
File: contracts-full/interfaces/ITransmuterBuffer.sol #45 37: event RegisterAsset(address underlyingToken, address transmuter);
File: contracts-full/interfaces/ITransmuterBuffer.sol #46 43: event SetFlowRate(address underlyingToken, uint256 flowRate);
File: contracts-full/interfaces/ITransmuterBuffer.sol #47 49: event SetSource(address source, bool flag);
File: contracts-full/interfaces/ITransmuterBuffer.sol #48 52: event SetTransmuter(address underlyingToken, address transmuter);
File: contracts-full/interfaces/IERC20Minimal.sol #49 11: event Transfer(address indexed owner, address indexed recipient, uint256 amount);
File: contracts-full/interfaces/IERC20Minimal.sol #50 18: event Approval(address indexed owner, address indexed spender, uint256 amount);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #51 9: event PendingAdminUpdated(address pendingAdmin);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #52 14: event AdminUpdated(address admin);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #53 20: event SentinelSet(address sentinel, bool flag);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #54 26: event KeeperSet(address sentinel, bool flag);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #55 42: event UnderlyingTokenEnabled(address indexed underlyingToken, bool enabled);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #56 48: event YieldTokenEnabled(address indexed yieldToken, bool enabled);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #57 55: event RepayLimitUpdated(address indexed underlyingToken, uint256 maximum, uint256 blocks);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #58 62: event LiquidationLimitUpdated(address indexed underlyingToken, uint256 maximum, uint256 blocks);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #59 67: event TransmuterUpdated(address transmuter);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #60 72: event MinimumCollateralizationUpdated(uint256 minimumCollateralization);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #61 77: event ProtocolFeeUpdated(uint256 protocolFee);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #62 82: event ProtocolFeeReceiverUpdated(address protocolFeeReceiver);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #63 88: event MintingLimitUpdated(uint256 maximum, uint256 blocks);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #64 94: event CreditUnlockRateUpdated(address yieldToken, uint256 blocks);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #65 100: event TokenAdapterUpdated(address yieldToken, address tokenAdapter);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #66 106: event MaximumExpectedValueUpdated(address indexed yieldToken, uint256 maximumExpectedValue);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #67 112: event MaximumLossUpdated(address indexed yieldToken, uint256 maximumLoss);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #68 118: event Snap(address indexed yieldToken, uint256 expectedValue);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #69 124: event SweepTokens(address indexed rewardToken, uint256 amount);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #70 131: event ApproveMint(address indexed owner, address indexed spender, uint256 amount);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #71 150: event Deposit(address indexed sender, address indexed yieldToken, uint256 amount, address recipient);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #72 162: event Withdraw(address indexed owner, address indexed yieldToken, uint256 shares, address recipient);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #73 169: event Mint(address indexed owner, uint256 amount, address recipient);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #74 176: event Burn(address indexed sender, uint256 amount, address recipient);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #75 184: event Repay(address indexed sender, address indexed underlyingToken, uint256 amount, address recipient);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #76 199: event Donate(address indexed sender, address indexed yieldToken, uint256 amount);
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #77 206: event Harvest(address indexed yieldToken, uint256 minimumAmountOut, uint256 totalHarvested);
File: contracts-full/ThreePoolAssetManager.sol #78 72: event AdminUpdated(address admin);
File: contracts-full/ThreePoolAssetManager.sol #79 77: event PendingAdminUpdated(address pendingAdmin);
File: contracts-full/ThreePoolAssetManager.sol #80 82: event OperatorUpdated(address operator);
File: contracts-full/ThreePoolAssetManager.sol #81 87: event RewardReceiverUpdated(address rewardReceiver);
File: contracts-full/ThreePoolAssetManager.sol #82 92: event TransmuterBufferUpdated(address transmuterBuffer);
File: contracts-full/ThreePoolAssetManager.sol #83 97: event ThreePoolSlippageUpdated(uint256 threePoolSlippage);
File: contracts-full/ThreePoolAssetManager.sol #84 102: event MetaPoolSlippageUpdated(uint256 metaPoolSlippage);
File: contracts-full/ThreePoolAssetManager.sol #85 108: event MintThreePoolTokens(uint256[NUM_STABLE_COINS] amounts, uint256 mintedThreePoolTokens);
File: contracts-full/ThreePoolAssetManager.sol #86 115: event MintThreePoolTokens(ThreePoolAsset asset, uint256 amount, uint256 mintedThreePoolTokens);
File: contracts-full/ThreePoolAssetManager.sol #87 122: event BurnThreePoolTokens(ThreePoolAsset asset, uint256 amount, uint256 withdrawn);
File: contracts-full/ThreePoolAssetManager.sol #88 128: event MintMetaPoolTokens(uint256[NUM_META_COINS] amounts, uint256 mintedThreePoolTokens);
File: contracts-full/ThreePoolAssetManager.sol #89 135: event MintMetaPoolTokens(MetaPoolAsset asset, uint256 amount, uint256 minted);
File: contracts-full/ThreePoolAssetManager.sol #90 142: event BurnMetaPoolTokens(MetaPoolAsset asset, uint256 amount, uint256 withdrawn);
File: contracts-full/ThreePoolAssetManager.sol #91 148: event DepositMetaPoolTokens(uint256 amount, bool success);
File: contracts-full/ThreePoolAssetManager.sol #92 154: event WithdrawMetaPoolTokens(uint256 amount, bool success);
File: contracts-full/ThreePoolAssetManager.sol #93 161: event ClaimRewards(bool success, uint256 amountCurve, uint256 amountConvex);
File: contracts-full/ThreePoolAssetManager.sol #94 167: event ReclaimThreePoolAsset(ThreePoolAsset asset, uint256 amount);
File: contracts-full/CrossChainCanonicalBase.sol #95 188: event BridgeTokenToggled(address indexed bridgeTokenAddress, bool state);
File: contracts-full/CrossChainCanonicalBase.sol #96 189: event SwapFeeSet(address indexed bridgeTokenAddress, uint bridgeToCanonical, uint canonicalToOld);
File: contracts-full/EthAssetManager.sol #97 59: event AdminUpdated(address admin);
File: contracts-full/EthAssetManager.sol #98 64: event PendingAdminUpdated(address pendingAdmin);
File: contracts-full/EthAssetManager.sol #99 69: event OperatorUpdated(address operator);
File: contracts-full/EthAssetManager.sol #100 74: event RewardReceiverUpdated(address rewardReceiver);
File: contracts-full/EthAssetManager.sol #101 79: event TransmuterBufferUpdated(address transmuterBuffer);
File: contracts-full/EthAssetManager.sol #102 84: event MetaPoolSlippageUpdated(uint256 metaPoolSlippage);
File: contracts-full/EthAssetManager.sol #103 90: event MintMetaPoolTokens(uint256[NUM_META_COINS] amounts, uint256 mintedThreePoolTokens);
File: contracts-full/EthAssetManager.sol #104 97: event MintMetaPoolTokens(MetaPoolAsset asset, uint256 amount, uint256 minted);
File: contracts-full/EthAssetManager.sol #105 104: event BurnMetaPoolTokens(MetaPoolAsset asset, uint256 amount, uint256 withdrawn);
File: contracts-full/EthAssetManager.sol #106 110: event DepositMetaPoolTokens(uint256 amount, bool success);
File: contracts-full/EthAssetManager.sol #107 116: event WithdrawMetaPoolTokens(uint256 amount, bool success);
File: contracts-full/EthAssetManager.sol #108 123: event ClaimRewards(bool success, uint256 amountCurve, uint256 amountConvex);
File: contracts-full/EthAssetManager.sol #109 128: event ReclaimEth(uint256 amount);
File: contracts-full/EthAssetManager.sol #110 134: event SweepToken(address token, uint256 amount);
File: contracts-full/EthAssetManager.sol #111 139: event SweepEth(uint256 amount);
There is 1 instance of this issue:
File: contracts-full/AlchemicTokenV1.sol #1 110: function setBlacklist(address minter) external onlySentinel {
#0 - liveactionllama
2022-05-19T19:02:34Z
Warden created this issue as a placeholder, because their submission was too large for the contest form. They then emailed their md file to our team on 05/18/2022 at 23:58 UTC. I've updated this issue with their md file content.
#1 - 0xfoobar
2022-05-30T07:12:45Z
Incredibly comprehensive, great writeup
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xf15ers, 0xkatana, 0xsomeone, AlleyCat, BowTiedWardens, Cityscape, Fitraldys, Funen, GimelSec, Hawkeye, JC, MaratCerby, MiloTruck, Randyyy, TerrierLover, Tomio, UnusualTurtle, WatchPug, Waze, _Adam, augustg, bobirichman, catchup, csanuragjain, ellahi, fatherOfBlocks, hake, hansfriese, horsefacts, ignacio, joestakey, kenta, mics, oyc_109, robee, samruna, sashik_eth, sikorico, simon135, throttle
872.8564 DAI - $872.86
Saves a storage slot. If the variable is assigned a non-zero value, saves Gsset (20000 gas). If it's assigned a zero value, saves Gsreset (2900 gas). If the variable remains unassigned, there is no gas savings. If the state variable is overriding an interface's public function, mark the variable as constant
or immutable
so that it does not use a storage slot, and manually add a getter function
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #1 29 string public override version = "1.0.0";
File: contracts-full/adapters/rocket/RETHAdapterV1.sol #2 32 string public override version = "1.0.0";
File: contracts-full/adapters/vesper/VesperAdapterV1.sol #3 30 string public override version = "1.0.0";
File: contracts-full/adapters/fuse/FuseTokenAdapterV1.sol #4 29 string public override version = "1.0.0";
address
mappings can be combined into a single mapping
of an address
to a struct
, where appropriateSaves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot
File: contracts-full/AlchemicTokenV2Base.sol #1 34 mapping(address => bool) public whitelisted; 35 36 /// @notice A set of addresses which are paused from minting new tokens. 37 mapping(address => bool) public paused; 38 39 /// @notice The amount that each address is permitted to mint. 40 mapping(address => uint256) public mintCeiling; 41 42 /// @notice The amount of tokens that each address has already minted. 43 mapping(address => uint256) public totalMinted;
File: contracts-full/TransmuterBuffer.sol #2 43 mapping(address => address) public transmuter; 44 45 /// @notice The flowRate for each address. 46 mapping(address => uint256) public flowRate; 47 48 /// @notice The last update timestamp gor the flowRate for each address. 49 mapping(address => uint256) public lastFlowrateUpdate; 50 51 /// @notice The amount of flow available per ERC20. 52 mapping(address => uint256) public flowAvailable; 53 54 /// @notice The yieldTokens of each underlying supported by the Alchemist. 55 mapping(address => address[]) public _yieldTokens; 56 57 /// @notice The total amount of an underlying token that has been exchanged into the transmuter, and has not been claimed. 58 mapping(address => uint256) public currentExchanged;
File: contracts-full/TransmuterBuffer.sol #3 67 mapping(address => Weighting) public weightings; 68 69 /// @dev A mapping of addresses to denote permissioned sources of funds 70 mapping(address => bool) public sources; 71 72 /// @dev A mapping of addresses to their respective AMOs. 73 mapping(address => address) public amos; 74 75 /// @dev A mapping of underlying tokens to divert to the AMO. 76 mapping(address => bool) public divertToAmo;
File: contracts-full/AlchemicTokenV1.sol #4 28 mapping (address => bool) public whiteList; 29 30 /// @notice A set of addresses which are blacklisted from minting new tokens. 31 mapping (address => bool) public blacklist; 32 33 /// @notice A set of addresses which are paused from minting new tokens. 34 mapping (address => bool) public paused; 35 36 /// @notice The amount that each address is permitted to mint. 37 mapping (address => uint256) public ceiling; 38 39 /// @notice The amount of tokens that each address has already minted. 40 mapping (address => uint256) public hasMinted;
File: contracts-full/AlchemicTokenV2.sol #5 33 mapping(address => bool) public whitelisted; 34 35 /// @notice A set of addresses which are paused from minting new tokens. 36 mapping(address => bool) public paused;
File: contracts-full/CrossChainCanonicalBase.sol #6 20 mapping(address => uint256[2]) public swapFees; 21 mapping(address => bool) public feeExempt;
File: contracts-full/AlchemistV2.sol #7 66 mapping(address => bool) public override sentinels; 67 68 /// @inheritdoc IAlchemistV2State 69 mapping(address => bool) public override keepers;
File: contracts-full/AlchemistV2.sol #8 90 mapping(address => Limiters.LinearGrowthLimiter) private _repayLimiters; 91 92 // @dev The liquidation limiters for each underlying token. 93 mapping(address => Limiters.LinearGrowthLimiter) private _liquidationLimiters; 94 95 /// @dev Accounts mapped by the address that owns them. 96 mapping(address => Account) private _accounts; 97 98 /// @dev Underlying token parameters mapped by token address. 99 mapping(address => UnderlyingTokenParams) private _underlyingTokens; 100 101 /// @dev Yield token parameters mapped by token address. 102 mapping(address => YieldTokenParams) private _yieldTokens;
immutable
Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmacces (100 gas) with a PUSH32
(3 gas). If getters are still desired, '_' can be added to the variable name and the getter can be added manually
File: contracts-full/StakingPools.sol #1 82 IERC20Mintable public reward;
File: contracts-full/WETHGateway.sol #2 20 address public whitelist;
File: contracts-full/TransmuterConduit.sol #3 13 address public token;
File: contracts-full/TransmuterConduit.sol #4 16 address public sourceTransmuter;
File: contracts-full/TransmuterConduit.sol #5 19 address public sinkTransmuter;
File: contracts-full/EthAssetManager.sol #6 157 IWETH9 public weth;
Each slot saved can avoid an extra Gsset (20000 gas) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings
File: contracts-full/interfaces/external/yearn/IYearnVaultV2.sol #1 10 struct StrategyParams { 11 uint256 performanceFee; 12 uint256 activation; 13 uint256 debtRatio; 14 uint256 minDebtPerHarvest; 15 uint256 maxDebtPerHarvest; 16 uint256 lastReport; 17 uint256 totalDebt; 18 uint256 totalGain; 19 uint256 totalLoss; 20 bool enforceChangeLimit; 21 uint256 profitLimitRatio; 22 uint256 lossLimitRatio; 23 address customCheck; 24 }
Variable ordering with 12 slots instead of the current 13: uint256(32):performanceFee, uint256(32):activation, uint256(32):debtRatio, uint256(32):minDebtPerHarvest, uint256(32):maxDebtPerHarvest, uint256(32):lastReport, uint256(32):totalDebt, uint256(32):totalGain, uint256(32):totalLoss, uint256(32):profitLimitRatio, uint256(32):lossLimitRatio, address(20):customCheck, bool(1):enforceChangeLimit https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/interfaces/external/yearn/IYearnVaultV2.sol#L10-L24
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #2 7 struct UnderlyingTokenParams { 8 // The number of decimals the token has. This value is cached once upon registering the token so it is important 9 // that the decimals of the token are immutable or the system will begin to have computation errors. 10 uint8 decimals; 11 // A coefficient used to normalize the token to a value comparable to the debt token. For example, if the 12 // underlying token is 8 decimals and the debt token is 18 decimals then the conversion factor will be 13 // 10^10. One unit of the underlying token will be comparably equal to one unit of the debt token. 14 uint256 conversionFactor; 15 // A flag to indicate if the token is enabled. 16 bool enabled; 17 }
Variable ordering with 2 slots instead of the current 3: uint256(32):conversionFactor, uint8(1):decimals, bool(1):enabled https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/interfaces/alchemist/IAlchemistV2State.sol#L7-L17
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #3 20 struct YieldTokenParams { 21 // The number of decimals the token has. This value is cached once upon registering the token so it is important 22 // that the decimals of the token are immutable or the system will begin to have computation errors. 23 uint8 decimals; 24 // The associated underlying token that can be redeemed for the yield-token. 25 address underlyingToken; 26 // The adapter used by the system to wrap, unwrap, and lookup the conversion rate of this token into its 27 // underlying token. 28 address adapter; 29 // The maximum percentage loss that is acceptable before disabling certain actions. 30 uint256 maximumLoss; 31 // The maximum value of yield tokens that the system can hold, measured in units of the underlying token. 32 uint256 maximumExpectedValue; 33 // The percent of credit that will be unlocked per block. The representation of this value is a 18 decimal 34 // fixed point integer. 35 uint256 creditUnlockRate; 36 // The current balance of yield tokens which are held by users. 37 uint256 activeBalance; 38 // The current balance of yield tokens which are earmarked to be harvested by the system at a later time. 39 uint256 harvestableBalance; 40 // The total number of shares that have been minted for this token. 41 uint256 totalShares; 42 // The expected value of the tokens measured in underlying tokens. This value controls how much of the token 43 // can be harvested. When users deposit yield tokens, it increases the expected value by how much the tokens 44 // are exchangeable for in the underlying token. When users withdraw yield tokens, it decreases the expected 45 // value by how much the tokens are exchangeable for in the underlying token. 46 uint256 expectedValue; 47 // The current amount of credit which is will be distributed over time to depositors. 48 uint256 pendingCredit; 49 // The amount of the pending credit that has been distributed. 50 uint256 distributedCredit; 51 // The block number which the last credit distribution occurred. 52 uint256 lastDistributionBlock; 53 // The total accrued weight. This is used to calculate how much credit a user has been granted over time. The 54 // representation of this value is a 18 decimal fixed point integer. 55 uint256 accruedWeight; 56 // A flag to indicate if the token is enabled. 57 bool enabled; 58 }
Variable ordering with 13 slots instead of the current 14: uint256(32):maximumLoss, uint256(32):maximumExpectedValue, uint256(32):creditUnlockRate, uint256(32):activeBalance, uint256(32):harvestableBalance, uint256(32):totalShares, uint256(32):expectedValue, uint256(32):pendingCredit, uint256(32):distributedCredit, uint256(32):lastDistributionBlock, uint256(32):accruedWeight, address(20):underlyingToken, uint8(1):decimals, bool(1):enabled, address(20):adapter https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/interfaces/alchemist/IAlchemistV2State.sol#L20-L58
calldata
instead of memory
for read-only arguments in external
functions saves gasWhen a function with a memory
array is called externally, the abi.decode()
step has to use a for-loop to copy each index of the calldata
to the memory
index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length
). Using calldata
directly, obliviates the need for such a loop in the contract code and runtime execution. Structs have the same overhead as an array of length one
File: contracts-full/TransmuterBuffer.sol #1 180 address[] memory tokens,
File: contracts-full/TransmuterBuffer.sol #2 181 uint256[] memory weights
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #3 163 function setWeights(address weightToken, address[] memory tokens, uint256[] memory weights) external;
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #4 163 function setWeights(address weightToken, address[] memory tokens, uint256[] memory weights) external;
File: contracts-full/interfaces/external/IProxyAdmin.sol #5 17 bytes memory data
File: contracts-full/interfaces/vesper/IVesperPool.sol #6 15 function multiTransfer(address[] memory _recipients, uint256[] memory _amounts)
File: contracts-full/interfaces/vesper/IVesperPool.sol #7 15 function multiTransfer(address[] memory _recipients, uint256[] memory _amounts)
File: contracts-full/interfaces/ITransmuterBuffer.sol #8 135 function setWeights(address weightToken, address[] memory tokens, uint256[] memory weights) external;
File: contracts-full/interfaces/ITransmuterBuffer.sol #9 135 function setWeights(address weightToken, address[] memory tokens, uint256[] memory weights) external;
File: contracts-full/interfaces/IStakingPools.sol #10 27 function setRewardWeights(uint256[] memory _rewardWeights) external;
File: contracts-full/interfaces/alchemist/IAlchemistV2AdminActions.sol #11 75 function initialize(InitializationParams memory params) external;
File: contracts-full/AlchemistV2.sol #12 255 function initialize(InitializationParams memory params) external initializer {
The instances below point to the second+ access of a state variable within a function. Caching will replace each Gwarmaccess (100 gas) with a much cheaper stack read. Less obvious fixes/optimizations include having local storage variables of mappings within state variable mappings or mappings within state variable structs, having local storage variables of structs within mappings, having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.
File: contracts-full/AlchemicTokenV2Base.sol #1 100 emit SetFlashMintFee(flashMintFee);
File: contracts-full/TransmuterBuffer.sol #2 238 TokenUtils.safeApprove(debtToken, alchemist, 0);
File: contracts-full/TransmuterBuffer.sol #3 245 TokenUtils.safeApprove(debtToken, alchemist, type(uint256).max);
File: contracts-full/TransmuterBuffer.sol #4 247 emit SetAlchemist(alchemist);
File: contracts-full/TransmuterBuffer.sol #5 284 TokenUtils.safeApprove(underlyingToken, alchemist, type(uint256).max);
File: contracts-full/TransmuterBuffer.sol #6 374 address[] memory supportedUnderlyingTokens = IAlchemistV2(alchemist)
File: contracts-full/TransmuterBuffer.sol #7 390 IAlchemistV2.YieldTokenParams memory params = IAlchemistV2(alchemist)
File: contracts-full/TransmuterBuffer.sol #8 406 IAlchemistV2(alchemist).mint(credit, address(this));
File: contracts-full/TransmuterBuffer.sol #9 444 IAlchemistV2.YieldTokenParams memory params = IAlchemistV2(alchemist)
File: contracts-full/TransmuterBuffer.sol #10 446 uint256 tokensPerShare = IAlchemistV2(alchemist)
File: contracts-full/TransmuterBuffer.sol #11 515 (uint256 availableShares, uint256 lastAccruedWeight) = IAlchemistV2(alchemist).positions(address(this), token);
File: contracts-full/TransmuterBuffer.sol #12 522 IAlchemistV2(alchemist).withdrawUnderlying(token, wantShares, address(this), minimumAmountOut);
File: contracts-full/TransmuterBuffer.sol #13 154 return flowAvailable[underlyingToken];
File: contracts-full/TransmuterBuffer.sol #14 539 } else if (initialLocalBalance < flowAvailable[underlyingToken]) {
File: contracts-full/TransmuterBuffer.sol #15 541 want = flowAvailable[underlyingToken] - initialLocalBalance;
File: contracts-full/TransmuterBuffer.sol #16 550 if (localBalance > flowAvailable[underlyingToken]) {
File: contracts-full/TransmuterBuffer.sol #17 551 exchangeDelta = flowAvailable[underlyingToken] - currentExchanged[underlyingToken];
File: contracts-full/TransmuterBuffer.sol #18 173 totalBuffered += _getTotalBuffered(_yieldTokens[underlyingToken][i]);
File: contracts-full/TransmuterBuffer.sol #19 319 uint256 exchangeable = flowAvailable[underlyingToken] - currentExchanged[underlyingToken];
currentExchanged https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterBuffer.sol#L319
File: contracts-full/TransmuterBuffer.sol #20 236 TokenUtils.safeApprove(registeredUnderlyings[i], alchemist, 0);
registeredUnderlyings https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterBuffer.sol#L236
File: contracts-full/TransmuterBuffer.sol #21 242 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
registeredUnderlyings https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterBuffer.sol#L242
File: contracts-full/TransmuterBuffer.sol #22 243 TokenUtils.safeApprove(registeredUnderlyings[i], alchemist, type(uint256).max);
registeredUnderlyings https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterBuffer.sol#L243
File: contracts-full/TransmuterBuffer.sol #23 382 for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
registeredUnderlyings https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterBuffer.sol#L382
File: contracts-full/TransmuterBuffer.sol #24 245 TokenUtils.safeApprove(debtToken, alchemist, type(uint256).max);
File: contracts-full/TransmuterBuffer.sol #25 568 IERC20TokenReceiver(amos[underlyingToken]).onERC20Received(underlyingToken, amount);
File: contracts-full/StakingPools.sol #26 133 address _pendingGovernance = pendingGovernance;
pendingGovernance https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/StakingPools.sol#L133
File: contracts-full/StakingPools.sol #27 214 _stake.update(_pool, _ctx);
File: contracts-full/StakingPools.sol #28 228 _stake.update(_pool, _ctx);
File: contracts-full/StakingPools.sol #29 243 _stake.update(_pool, _ctx);
File: contracts-full/StakingPools.sol #30 259 _stake.update(_pool, _ctx);
File: contracts-full/StakingPools.sol #31 272 _stake.update(_pool, _ctx);
File: contracts-full/StakingPools.sol #32 188 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/TransmuterV2.sol #33 155 uint8 debtTokenDecimals = TokenUtils.expectDecimals(syntheticToken);
syntheticToken https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterV2.sol#L155
File: contracts-full/TransmuterV2.sol #34 156 uint8 underlyingTokenDecimals = TokenUtils.expectDecimals(underlyingToken);
underlyingToken https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterV2.sol#L156
File: contracts-full/TransmuterV2.sol #35 263 totalUnexchanged: totalUnexchanged,
totalUnexchanged https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterV2.sol#L263
File: contracts-full/TransmuterV2.sol #36 263 totalUnexchanged: totalUnexchanged,
totalUnexchanged https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterV2.sol#L263
File: contracts-full/TransmuterV2.sol #37 203 emit Paused(isPaused);
File: contracts-full/gALCX.sol #38 51 pools.withdraw(poolId, poolBalance);
File: contracts-full/gALCX.sol #39 58 pools.deposit(poolId, balance);
File: contracts-full/gALCX.sol #40 79 pools.deposit(poolId, balance);
File: contracts-full/gALCX.sol #41 51 pools.withdraw(poolId, poolBalance);
File: contracts-full/gALCX.sol #42 58 pools.deposit(poolId, balance);
File: contracts-full/gALCX.sol #43 79 pools.deposit(poolId, balance);
File: contracts-full/AlchemicTokenV2.sol #44 94 emit SetFlashMintFee(flashMintFee);
File: contracts-full/ThreePoolAssetManager.sol #45 258 emit AdminUpdated(admin);
File: contracts-full/ThreePoolAssetManager.sol #46 467 emit AdminUpdated(admin);
File: contracts-full/ThreePoolAssetManager.sol #47 464 admin = pendingAdmin;
File: contracts-full/ThreePoolAssetManager.sol #48 259 emit OperatorUpdated(operator);
File: contracts-full/ThreePoolAssetManager.sol #49 260 emit RewardReceiverUpdated(rewardReceiver);
File: contracts-full/ThreePoolAssetManager.sol #50 633 SafeERC20.safeTransfer(address(convexToken), rewardReceiver, convexBalance);
File: contracts-full/ThreePoolAssetManager.sol #51 1015 SafeERC20.safeTransfer(address(convexToken), rewardReceiver, convexBalance);
File: contracts-full/ThreePoolAssetManager.sol #52 261 emit TransmuterBufferUpdated(transmuterBuffer);
transmuterBuffer https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/ThreePoolAssetManager.sol#L261
File: contracts-full/ThreePoolAssetManager.sol #53 721 IERC20TokenReceiver(transmuterBuffer).onERC20Received(address(token), amount);
transmuterBuffer https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/ThreePoolAssetManager.sol#L721
File: contracts-full/ThreePoolAssetManager.sol #54 262 emit ThreePoolSlippageUpdated(threePoolSlippage);
threePoolSlippage https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/ThreePoolAssetManager.sol#L262
File: contracts-full/ThreePoolAssetManager.sol #55 263 emit MetaPoolSlippageUpdated(metaPoolSlippage);
metaPoolSlippage https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/ThreePoolAssetManager.sol#L263
File: contracts-full/TransmuterConduit.sol #56 36 IERC20TokenReceiver(sinkTransmuter).onERC20Received(token, amount);
File: contracts-full/TransmuterConduit.sol #57 36 IERC20TokenReceiver(sinkTransmuter).onERC20Received(token, amount);
sinkTransmuter https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/TransmuterConduit.sol#L36
File: contracts-full/EthAssetManager.sol #58 221 emit AdminUpdated(admin);
File: contracts-full/EthAssetManager.sol #59 315 emit AdminUpdated(admin);
File: contracts-full/EthAssetManager.sol #60 312 admin = pendingAdmin;
File: contracts-full/EthAssetManager.sol #61 222 emit OperatorUpdated(operator);
File: contracts-full/EthAssetManager.sol #62 223 emit RewardReceiverUpdated(rewardReceiver);
rewardReceiver https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L223
File: contracts-full/EthAssetManager.sol #63 429 SafeERC20.safeTransfer(address(convexToken), rewardReceiver, convexBalance);
rewardReceiver https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L429
File: contracts-full/EthAssetManager.sol #64 699 SafeERC20.safeTransfer(address(convexToken), rewardReceiver, convexBalance);
rewardReceiver https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L699
File: contracts-full/EthAssetManager.sol #65 224 emit TransmuterBufferUpdated(transmuterBuffer);
transmuterBuffer https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L224
File: contracts-full/EthAssetManager.sol #66 500 IERC20TokenReceiver(transmuterBuffer).onERC20Received(address(weth), amount);
transmuterBuffer https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L500
File: contracts-full/EthAssetManager.sol #67 217 _metaPoolAssetCache[i] = weth;
File: contracts-full/EthAssetManager.sol #68 496 if (amount > (balance = weth.balanceOf(address(this)))) weth.deposit{value: amount - balance}();
File: contracts-full/EthAssetManager.sol #69 498 SafeERC20.safeTransfer(address(weth), transmuterBuffer, amount);
File: contracts-full/EthAssetManager.sol #70 500 IERC20TokenReceiver(transmuterBuffer).onERC20Received(address(weth), amount);
File: contracts-full/EthAssetManager.sol #71 225 emit MetaPoolSlippageUpdated(metaPoolSlippage);
metaPoolSlippage https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L225
File: contracts-full/EthAssetManager.sol #72 216 if (_metaPoolAssetCache[i] == IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) {
_metaPoolAssetCache https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/EthAssetManager.sol#L216
File: contracts-full/AlchemistV2.sol #73 272 emit AdminUpdated(admin);
File: contracts-full/AlchemistV2.sol #74 298 emit AdminUpdated(admin);
File: contracts-full/AlchemistV2.sol #75 291 if (msg.sender != pendingAdmin) {
File: contracts-full/AlchemistV2.sol #76 295 admin = pendingAdmin;
File: contracts-full/AlchemistV2.sol #77 273 emit TransmuterUpdated(transmuter);
File: contracts-full/AlchemistV2.sol #78 795 IERC20TokenReceiver(transmuter).onERC20Received(underlyingToken, actualAmount);
File: contracts-full/AlchemistV2.sol #79 879 IERC20TokenReceiver(transmuter).onERC20Received(underlyingToken, amountUnderlyingTokens);
File: contracts-full/AlchemistV2.sol #80 945 IERC20TokenReceiver(transmuter).onERC20Received(underlyingToken, distributeAmount);
File: contracts-full/AlchemistV2.sol #81 274 emit MinimumCollateralizationUpdated(minimumCollateralization);
minimumCollateralization https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L274
File: contracts-full/AlchemistV2.sol #82 275 emit ProtocolFeeUpdated(protocolFee);
File: contracts-full/AlchemistV2.sol #83 276 emit ProtocolFeeReceiverUpdated(protocolFeeReceiver);
protocolFeeReceiver https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L276
File: contracts-full/AlchemistV2.sol #84 411 _repayLimiters[underlyingToken].configure(maximum, blocks);
_repayLimiters https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L411
File: contracts-full/AlchemistV2.sol #85 420 _liquidationLimiters[underlyingToken].configure(maximum, blocks);
_liquidationLimiters https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L420
File: contracts-full/AlchemistV2.sol #86 1464 uint256 shares = _accounts[owner].balances[yieldToken];
File: contracts-full/AlchemistV2.sol #87 1490 _accounts[recipient].depositedTokens.add(yieldToken);
File: contracts-full/AlchemistV2.sol #88 1493 _accounts[recipient].balances[yieldToken] += shares;
File: contracts-full/AlchemistV2.sol #89 1528 uint256 lastAccruedWeight = _accounts[owner].lastAccruedWeights[yieldToken];
File: contracts-full/AlchemistV2.sol #90 1539 uint256 balance = _accounts[owner].balances[yieldToken];
File: contracts-full/AlchemistV2.sol #91 900 _accounts[msg.sender].lastAccruedWeights[yieldToken] = _yieldTokens[yieldToken].accruedWeight;
The instances below point to the second+ call of the function within a single function
File: contracts-full/StakingPools.sol #1 188 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
_pools.length() https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/StakingPools.sol#L188
File: contracts-full/AlchemistV2.sol #2 364 underlyingToken: adapter.underlyingToken(),
adapter.underlyingToken() https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L364
File: contracts-full/AlchemistV2.sol #3 383 TokenUtils.safeApprove(adapter.underlyingToken(), config.adapter, type(uint256).max);
adapter.underlyingToken() https://github.com/code-423n4/2022-05-alchemix/blob/71abbe683dfd5c0686b7e594fb4f78a14b668d8b/contracts-full/AlchemistV2.sol#L383
<x> += <y>
costs more gas than <x> = <x> + <y>
for state variablesFile: contracts-full/TransmuterV2.sol #1 254 totalBuffered += normaizedAmount;
File: contracts-full/TransmuterV2.sol #2 343 totalBuffered += state.distributeAmount;
File: contracts-full/gALCX.sol #3 76 exchangeRate += (balance * exchangeRatePrecision) / totalSupply;
internal
functions only called once can be inlined to save gasNot inlining costs 20 to 40 gas because of two extra JUMP
instructions and additional stack operations needed for function calls.
File: contracts-full/TransmuterBuffer.sol #1 438 function _getTotalBuffered(address yieldToken) 439 internal 440 view 441 returns (uint256)
File: contracts-full/StakingPools.sol #2 375 function _deposit(uint256 _poolId, uint256 _depositAmount) internal {
File: contracts-full/StakingPools.sol #3 431 function _claimExact(uint256 _poolId, uint256 _claimAmount) internal {
File: contracts-full/TransmuterV2.sol #4 190 function _onlyAdmin() internal view { 191 if (!hasRole(ADMIN, msg.sender)) {
File: contracts-full/TransmuterV2.sol #5 550 function _normalizeDebtTokensToUnderlying(uint256 amount) internal view returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #6 744 function _getEarnedConvex(uint256 amountCurve) internal view returns (uint256) {
File: contracts-full/EthAssetManager.sol #7 542 function _getEarnedConvex(uint256 amountCurve) internal view returns (uint256) {
File: contracts-full/AlchemistV2.sol #8 979 function _onlyKeeper() internal view { 980 if (!keepers[msg.sender]) {
File: contracts-full/AlchemistV2.sol #9 1068 function _checkMintingLimit(uint256 amount) internal view {
File: contracts-full/AlchemistV2.sol #10 1243 function _loss(address yieldToken) internal view returns (uint256) {
File: contracts-full/AlchemistV2.sol #11 1258 function _distributeCredit(address yieldToken, uint256 amount) internal {
File: contracts-full/AlchemistV2.sol #12 1309 function _wrap( 1310 address yieldToken, 1311 uint256 amount, 1312 uint256 minimumAmountOut 1313 ) internal returns (uint256) {
File: contracts-full/AlchemistV2.sol #13 1395 function _approveMint(address owner, address spender, uint256 amount) internal {
File: contracts-full/AlchemistV2.sol #14 1406 function _decreaseMintAllowance(address owner, address spender, uint256 amount) internal {
File: contracts-full/AlchemistV2.sol #15 1417 function _approveWithdraw(address owner, address spender, address yieldToken, uint256 shares) internal {
File: contracts-full/AlchemistV2.sol #16 1457 function _totalValue(address owner) internal view returns (uint256) {
File: contracts-full/AlchemistV2.sol #17 1482 function _issueSharesForAmount( 1483 address recipient, 1484 address yieldToken, 1485 uint256 amount 1486 ) internal returns (uint256) {
File: contracts-full/AlchemistV2.sol #18 1669 function _convertUnderlyingTokensToShares(address yieldToken, uint256 amount) internal view returns (uint256) {
<array>.length
should not be looked up in every loop of a for
-loopThe overheads outlined below are PER LOOP, excluding the first loop
MLOAD
(3 gas)CALLDATALOAD
(3 gas)Caching the length changes each of these to a DUP<N>
(3 gas), and gets rid of the extra DUP<N>
needed to store the stack offset
File: contracts-full/TransmuterBuffer.sol #1 172 for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
File: contracts-full/TransmuterBuffer.sol #2 186 for (uint256 i = 0; i < tokens.length; i++) {
File: contracts-full/TransmuterBuffer.sol #3 235 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #4 242 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #5 272 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #6 382 for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
File: contracts-full/TransmuterBuffer.sol #7 479 for (uint256 j = 0; j < weighting.tokens.length; j++) {
File: contracts-full/base/Multicall.sol #8 14 for (uint256 i = 0; i < data.length; i++) {
File: contracts-full/CrossChainCanonicalBase.sol #9 57 for (uint256 i = 0; i < _bridgeTokens.length; i++){
File: contracts-full/CrossChainCanonicalBase.sol #10 141 for (uint i = 0; i < bridgeTokensArray.length; i++){
File: contracts-full/AlchemistV2.sol #11 990 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #12 1282 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #13 1355 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #14 1461 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #15 1524 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
++i
/i++
should be unchecked{++i}
/unchecked{++i}
when it is not possible for them to overflow, as is the case when used in for
- and while
-loopsThe unchecked
keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas PER LOOP
File: contracts-full/TransmuterBuffer.sol #1 172 for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
File: contracts-full/TransmuterBuffer.sol #2 186 for (uint256 i = 0; i < tokens.length; i++) {
File: contracts-full/TransmuterBuffer.sol #3 235 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #4 242 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #5 272 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #6 382 for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
File: contracts-full/TransmuterBuffer.sol #7 387 for (uint256 i = 0; i < numYTokens; i++) {
File: contracts-full/TransmuterBuffer.sol #8 479 for (uint256 j = 0; j < weighting.tokens.length; j++) {
File: contracts-full/StakingPools.sol #9 188 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/StakingPools.sol #10 363 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/base/Multicall.sol #11 14 for (uint256 i = 0; i < data.length; i++) {
File: contracts-full/ThreePoolAssetManager.sol #12 250 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #13 254 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #14 353 for (uint256 i = 0; i < 256; i++) {
File: contracts-full/ThreePoolAssetManager.sol #15 773 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #16 902 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/CrossChainCanonicalBase.sol #17 57 for (uint256 i = 0; i < _bridgeTokens.length; i++){
File: contracts-full/CrossChainCanonicalBase.sol #18 141 for (uint i = 0; i < bridgeTokensArray.length; i++){
File: contracts-full/EthAssetManager.sol #19 214 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/EthAssetManager.sol #20 567 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/AlchemistV2.sol #21 990 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #22 1282 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #23 1355 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #24 1461 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #25 1524 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
require()
/revert()
strings longer than 32 bytes cost extra gasFile: contracts-full/StakingPools.sol #1 106 require(_governance != address(0), "StakingPools: governance address cannot be 0x0");
File: contracts-full/StakingPools.sol #2 124 require(_pendingGovernance != address(0), "StakingPools: pending governance address cannot be 0x0");
File: contracts-full/StakingPools.sol #3 131 require(msg.sender == pendingGovernance, "StakingPools: only pending governance");
File: contracts-full/StakingPools.sol #4 160 require(tokenPoolIds[_token] == 0, "StakingPools: token already has a pool");
File: contracts-full/StakingPools.sol #5 183 require(_rewardWeights.length == _pools.length(), "StakingPools: weights length mismatch");
File: contracts-full/AlchemicTokenV1.sol #6 51 require(whiteList[msg.sender], "AlTokenV1: Alchemist is not whitelisted");
File: contracts-full/AlchemicTokenV1.sol #7 81 require(total <= ceiling[msg.sender], "AlUSD: Alchemist's ceiling was breached.");
private
functions not called by the contract should be removed to save deployment gasFile: contracts-full/ThreePoolAssetManager.sol #1 1026 function min(uint256 x , uint256 y) private pure returns (uint256) {
File: contracts-full/EthAssetManager.sol #2 710 function min(uint256 x , uint256 y) private pure returns (uint256) {
File: contracts-full/EthAssetManager.sol #3 720 function abs(uint256 x , uint256 y) private pure returns (uint256) {
File: contracts-full/AutoleverageCurveMetapool.sol #1 27 return ICurveMetapool(poolAddress).exchange_underlying( 28 i, 29 j, 30 debtTokenBalance, 31 minAmountOut 32 );
File: contracts-full/TransmuterBuffer.sol #2 136 return weightings[weightToken].weights[token];
File: contracts-full/AutoleverageCurveFactoryethpool.sol #3 41 return ICurveFactoryethpool(poolAddress).exchange( 42 i, 43 j, 44 debtTokenBalance, 45 minAmountOut 46 );
File: contracts-full/TransmuterV2.sol #4 354 return 0;
File: contracts-full/TransmuterV2.sol #5 371 return _getExchangedBalance(owner);
File: contracts-full/TransmuterV2.sol #6 375 return _normalizeDebtTokensToUnderlying(_getExchangedBalance(owner));
File: contracts-full/ThreePoolAssetManager.sol #7 399 return v.minimizedBalance > v.startingBalance 400 ? (v.minimizedBalance - v.startingBalance, true) 401 : (v.startingBalance - v.minimizedBalance, false);
File: contracts-full/ThreePoolAssetManager.sol #8 399 return v.minimizedBalance > v.startingBalance 400 ? (v.minimizedBalance - v.startingBalance, true) 401 : (v.startingBalance - v.minimizedBalance, false);
File: contracts-full/ThreePoolAssetManager.sol #9 535 return _mintThreePoolTokens(amounts);
File: contracts-full/ThreePoolAssetManager.sol #10 548 return _mintThreePoolTokens(asset, amount);
File: contracts-full/ThreePoolAssetManager.sol #11 561 return _burnThreePoolTokens(asset, amount);
File: contracts-full/ThreePoolAssetManager.sol #12 572 return _mintMetaPoolTokens(amounts);
File: contracts-full/ThreePoolAssetManager.sol #13 585 return _mintMetaPoolTokens(asset, amount);
File: contracts-full/ThreePoolAssetManager.sol #14 598 return _burnMetaPoolTokens(asset, amount);
File: contracts-full/ThreePoolAssetManager.sol #15 609 return _depositMetaPoolTokens(amount);
File: contracts-full/ThreePoolAssetManager.sol #16 620 return _withdrawMetaPoolTokens(amount);
File: contracts-full/EthAssetManager.sol #17 368 return _mintMetaPoolTokens(amounts);
File: contracts-full/EthAssetManager.sol #18 381 return _mintMetaPoolTokens(asset, amount);
File: contracts-full/EthAssetManager.sol #19 394 return _burnMetaPoolTokens(asset, amount);
File: contracts-full/EthAssetManager.sol #20 405 return _depositMetaPoolTokens(amount);
File: contracts-full/EthAssetManager.sol #21 416 return _withdrawMetaPoolTokens(amount);
File: contracts-full/AlchemistV2.sol #22 152 return ( 153 _calculateUnrealizedDebt(owner), 154 account.depositedTokens.values 155 );
File: contracts-full/AlchemistV2.sol #23 152 return ( 153 _calculateUnrealizedDebt(owner), 154 account.depositedTokens.values 155 );
File: contracts-full/AlchemistV2.sol #24 167 return (account.balances[yieldToken], account.lastAccruedWeights[yieldToken]);
File: contracts-full/AlchemistV2.sol #25 167 return (account.balances[yieldToken], account.lastAccruedWeights[yieldToken]);
File: contracts-full/AlchemistV2.sol #26 213 return ( 214 _mintingLimiter.get(), 215 _mintingLimiter.rate, 216 _mintingLimiter.maximum 217 );
File: contracts-full/AlchemistV2.sol #27 213 return ( 214 _mintingLimiter.get(), 215 _mintingLimiter.rate, 216 _mintingLimiter.maximum 217 );
File: contracts-full/AlchemistV2.sol #28 213 return ( 214 _mintingLimiter.get(), 215 _mintingLimiter.rate, 216 _mintingLimiter.maximum 217 );
File: contracts-full/AlchemistV2.sol #29 230 return ( 231 limiter.get(), 232 limiter.rate, 233 limiter.maximum 234 );
File: contracts-full/AlchemistV2.sol #30 230 return ( 231 limiter.get(), 232 limiter.rate, 233 limiter.maximum 234 );
File: contracts-full/AlchemistV2.sol #31 230 return ( 231 limiter.get(), 232 limiter.rate, 233 limiter.maximum 234 );
File: contracts-full/AlchemistV2.sol #32 247 return ( 248 limiter.get(), 249 limiter.rate, 250 limiter.maximum 251 );
File: contracts-full/AlchemistV2.sol #33 247 return ( 248 limiter.get(), 249 limiter.rate, 250 limiter.maximum 251 );
File: contracts-full/AlchemistV2.sol #34 247 return ( 248 limiter.get(), 249 limiter.rate, 250 limiter.maximum 251 );
File: contracts-full/TransmuterBuffer.sol #1 515 (uint256 availableShares, uint256 lastAccruedWeight) = IAlchemistV2(alchemist).positions(address(this), token);
bool
s for storage incurs overhead// Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27
Use uint256(1)
and uint256(2)
for true/false
File: contracts-full/AlchemicTokenV2Base.sol #1 34 mapping(address => bool) public whitelisted;
File: contracts-full/AlchemicTokenV2Base.sol #2 37 mapping(address => bool) public paused;
File: contracts-full/TransmuterBuffer.sol #3 70 mapping(address => bool) public sources;
File: contracts-full/TransmuterBuffer.sol #4 76 mapping(address => bool) public divertToAmo;
File: contracts-full/utils/Whitelist.sol #5 15 bool public override disabled;
File: contracts-full/AlchemicTokenV1.sol #6 28 mapping (address => bool) public whiteList;
File: contracts-full/AlchemicTokenV1.sol #7 31 mapping (address => bool) public blacklist;
File: contracts-full/AlchemicTokenV1.sol #8 34 mapping (address => bool) public paused;
File: contracts-full/TransmuterV2.sol #9 130 bool public isPaused;
File: contracts-full/AlchemicTokenV2.sol #10 33 mapping(address => bool) public whitelisted;
File: contracts-full/AlchemicTokenV2.sol #11 36 mapping(address => bool) public paused;
File: contracts-full/CrossChainCanonicalBase.sol #12 21 mapping(address => bool) public feeExempt;
File: contracts-full/CrossChainCanonicalBase.sol #13 25 mapping(address => bool) public bridgeTokens; // Used for the logic checks
File: contracts-full/CrossChainCanonicalBase.sol #14 28 bool public exchangesPaused; // Pause old token exchanges in case of an emergency
File: contracts-full/CrossChainCanonicalBase.sol #15 29 mapping(address => bool) public bridgeTokenEnabled;
File: contracts-full/AlchemistV2.sol #16 66 mapping(address => bool) public override sentinels;
File: contracts-full/AlchemistV2.sol #17 69 mapping(address => bool) public override keepers;
Use a solidity version of at least 0.8.0 to get overflow protection without SafeMath
Use a solidity version of at least 0.8.2 to get compiler automatic inlining
Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads
Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require()
strings
Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
File: contracts-full/base/SelfPermit.sol #1 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20PermitAllowed.sol #2 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/lido/IWstETH.sol #3 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/lido/IStETH.sol #4 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Mintable.sol #5 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #6 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/curve/IStableMetaPool.sol #7 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #8 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #9 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/convex/IConvexToken.sol #10 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/convex/IConvexBooster.sol #11 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/convex/IConvexRewards.sol #12 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC3156FlashLender.sol #13 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IWETH9.sol #14 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Burnable.sol #15 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/transmuter/ITransmuterBuffer.sol #16 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/transmuter/ITransmuterV2.sol #17 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/ISelfPermit.sol #18 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/rocket/IRocketStorage.sol #19 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/rocket/IRETH.sol #20 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/IAToken.sol #21 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/IWethGateway.sol #22 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/IScaledBalanceToken.sol #23 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/ILendingPoolAddressesProviderRegistry.sol #24 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/DataTypes.sol #25 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/ILendingPool.sol #26 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/IStaticAToken.sol #27 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/aave/ILendingPoolAddressesProvider.sol #28 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/maker/IDssProxyActions.sol #29 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/uniswap/ISwapRouter.sol #30 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/IWETH9.sol #31 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/tether/ITetherToken.sol #32 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/external/yearn/IYearnVaultV2.sol #33 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/ITransmuterV1.sol #34 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IAlchemistV2.sol #35 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/vesper/IVesperRewards.sol #36 4 pragma solidity >=0.6.12;
File: contracts-full/interfaces/vesper/IVesperPool.sol #37 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/ITokenAdapter.sol #38 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IWETHGateway.sol #39 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/ITransmuterBuffer.sol #40 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Minimal.sol #41 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IMulticall.sol #42 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20TokenReceiver.sol #43 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Actions.sol #44 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Events.sol #45 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #46 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2AdminActions.sol #47 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Errors.sol #48 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/alchemist/IAlchemistV2Immutables.sol #49 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC20Metadata.sol #50 1 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IERC3156FlashBorrower.sol #51 2 pragma solidity >=0.5.0;
File: contracts-full/interfaces/IAlchemicToken.sol #52 2 pragma solidity >=0.5.0;
File: contracts-full/libraries/LiquidityMath.sol #53 2 pragma solidity >=0.5.0;
File: contracts-full/libraries/SafeCast.sol #54 2 pragma solidity >=0.5.0;
File: contracts-full/libraries/RocketPool.sol #55 1 pragma solidity >=0.5.0;
File: contracts-full/libraries/Tick.sol #56 2 pragma solidity >=0.5.0;
Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
File: contracts-full/libraries/SafeERC20.sol #1 2 pragma solidity >=0.8.4;
Use a solidity version of at least 0.8.2 to get compiler automatic inlining
Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads
Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment than revert()/require()
strings
Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value
File: contracts-full/interfaces/external/IProxyAdmin.sol #1 3 pragma solidity ^0.8.0;
File: contracts-full/TransmuterBuffer.sol #1 172 for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
File: contracts-full/TransmuterBuffer.sol #2 186 for (uint256 i = 0; i < tokens.length; i++) {
File: contracts-full/TransmuterBuffer.sol #3 235 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #4 242 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #5 272 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #6 382 for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
File: contracts-full/TransmuterBuffer.sol #7 387 for (uint256 i = 0; i < numYTokens; i++) {
File: contracts-full/TransmuterBuffer.sol #8 479 for (uint256 j = 0; j < weighting.tokens.length; j++) {
File: contracts-full/TransmuterBuffer.sol #9 534 uint256 want = 0;
File: contracts-full/TransmuterBuffer.sol #10 549 uint256 exchangeDelta = 0;
File: contracts-full/StakingPools.sol #11 188 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/StakingPools.sol #12 363 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/base/Multicall.sol #13 14 for (uint256 i = 0; i < data.length; i++) {
File: contracts-full/TransmuterV2.sol #14 96 address public constant ZERO_ADDRESS = address(0);
File: contracts-full/ThreePoolAssetManager.sol #15 250 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #16 254 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #17 353 for (uint256 i = 0; i < 256; i++) {
File: contracts-full/ThreePoolAssetManager.sol #18 771 uint256 normalizedTotal = 0;
File: contracts-full/ThreePoolAssetManager.sol #19 773 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #20 901 uint256 total = 0;
File: contracts-full/ThreePoolAssetManager.sol #21 902 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/CrossChainCanonicalBase.sol #22 57 for (uint256 i = 0; i < _bridgeTokens.length; i++){
File: contracts-full/CrossChainCanonicalBase.sol #23 141 for (uint i = 0; i < bridgeTokensArray.length; i++){
File: contracts-full/EthAssetManager.sol #24 214 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/EthAssetManager.sol #25 566 uint256 total = 0;
File: contracts-full/EthAssetManager.sol #26 567 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/AlchemistV2.sol #27 990 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #28 1282 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #29 1355 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #30 1458 uint256 totalValue = 0;
File: contracts-full/AlchemistV2.sol #31 1461 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #32 1524 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
internal
functions not called by the contract should be removed to save deployment gasIf the functions are required by an interface, the contract should inherit from that interface and use the override
keyword
File: contracts-full/TransmuterBuffer.sol #1 490 function _alchemistDonate(address token, uint256 amount) internal {
File: contracts-full/TransmuterBuffer.sol #2 498 function _alchemistDeposit(address token, uint256 amount) internal {
File: contracts-full/TransmuterBuffer.sol #3 511 function _alchemistWithdraw(address token, uint256 amountUnderlying) internal {
File: contracts-full/ThreePoolAssetManager.sol #4 1008 function _claimRewards() internal returns (bool success) {
File: contracts-full/EthAssetManager.sol #5 692 function _claimRewards() internal returns (bool success) {
File: contracts-full/AlchemistV2.sol #6 1740 function _uadd(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x + y; }
File: contracts-full/AlchemistV2.sol #7 1750 function _usub(uint256 x, uint256 y) internal pure returns (uint256 z) { z = x - y; }
++i
costs less gas than ++i
, especially when it's used in for
-loops (--i
/i--
too)Saves 6 gas PER LOOP
File: contracts-full/TransmuterBuffer.sol #1 172 for (uint256 i = 0; i < _yieldTokens[underlyingToken].length; i++) {
File: contracts-full/TransmuterBuffer.sol #2 186 for (uint256 i = 0; i < tokens.length; i++) {
File: contracts-full/TransmuterBuffer.sol #3 235 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #4 242 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #5 272 for (uint256 i = 0; i < registeredUnderlyings.length; i++) {
File: contracts-full/TransmuterBuffer.sol #6 382 for (uint256 j = 0; j < registeredUnderlyings.length; j++) {
File: contracts-full/TransmuterBuffer.sol #7 387 for (uint256 i = 0; i < numYTokens; i++) {
File: contracts-full/TransmuterBuffer.sol #8 479 for (uint256 j = 0; j < weighting.tokens.length; j++) {
File: contracts-full/StakingPools.sol #9 188 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/StakingPools.sol #10 363 for (uint256 _poolId = 0; _poolId < _pools.length(); _poolId++) {
File: contracts-full/base/Multicall.sol #11 14 for (uint256 i = 0; i < data.length; i++) {
File: contracts-full/ThreePoolAssetManager.sol #12 250 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #13 254 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #14 353 for (uint256 i = 0; i < 256; i++) {
File: contracts-full/ThreePoolAssetManager.sol #15 773 for (uint256 i = 0; i < NUM_STABLE_COINS; i++) {
File: contracts-full/ThreePoolAssetManager.sol #16 902 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/CrossChainCanonicalBase.sol #17 57 for (uint256 i = 0; i < _bridgeTokens.length; i++){
File: contracts-full/CrossChainCanonicalBase.sol #18 141 for (uint i = 0; i < bridgeTokensArray.length; i++){
File: contracts-full/EthAssetManager.sol #19 214 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/EthAssetManager.sol #20 567 for (uint256 i = 0; i < NUM_META_COINS; i++) {
File: contracts-full/AlchemistV2.sol #21 990 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #22 1282 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #23 1355 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #24 1461 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
File: contracts-full/AlchemistV2.sol #25 1524 for (uint256 i = 0; i < depositedTokens.values.length; i++) {
uints
/ints
smaller than 32 bytes (256 bits) incurs overheadWhen using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed
File: contracts-full/AutoleverageCurveMetapool.sol #1 23 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) {
File: contracts-full/AutoleverageCurveMetapool.sol #2 23 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) {
File: contracts-full/TransmuterBuffer.sol #3 512 uint8 decimals = TokenUtils.expectDecimals(token);
File: contracts-full/AutoleverageCurveFactoryethpool.sol #4 37 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) {
File: contracts-full/AutoleverageCurveFactoryethpool.sol #5 37 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) {
File: contracts-full/base/SelfPermit.sol #6 22 uint8 v,
File: contracts-full/base/SelfPermit.sol #7 34 uint8 v,
File: contracts-full/base/SelfPermit.sol #8 46 uint8 v,
File: contracts-full/base/SelfPermit.sol #9 58 uint8 v,
File: contracts-full/TransmuterV2.sol #10 155 uint8 debtTokenDecimals = TokenUtils.expectDecimals(syntheticToken);
File: contracts-full/TransmuterV2.sol #11 156 uint8 underlyingTokenDecimals = TokenUtils.expectDecimals(underlyingToken);
File: contracts-full/interfaces/IERC20PermitAllowed.sol #12 27 uint8 v,
File: contracts-full/interfaces/ICurveFactoryethpool.sol #13 11 function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external payable returns (uint256);
File: contracts-full/interfaces/ICurveFactoryethpool.sol #14 11 function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external payable returns (uint256);
File: contracts-full/interfaces/ICurveMetapool.sol #15 11 function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256);
File: contracts-full/interfaces/ICurveMetapool.sol #16 11 function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #17 20 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #18 20 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #19 22 function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #20 22 function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #21 25 int128 i,
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #22 26 int128 j,
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #23 38 function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256);
File: contracts-full/interfaces/curve/IStableSwap2Pool.sol #24 42 int128 i,
File: contracts-full/interfaces/curve/IStableMetaPool.sol #25 28 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #26 28 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #27 30 function get_dy_underlying(int128 i, int128 j, uint256 dx, uint256[N_COINS] calldata balances) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #28 30 function get_dy_underlying(int128 i, int128 j, uint256 dx, uint256[N_COINS] calldata balances) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #29 32 function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #30 32 function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #31 41 function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256);
File: contracts-full/interfaces/curve/IStableMetaPool.sol #32 45 int128 i,
File: contracts-full/interfaces/curve/IStableMetaPool.sol #33 60 int128 i,
File: contracts-full/interfaces/curve/IStableMetaPool.sol #34 61 int128 j,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #35 27 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #36 27 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #37 30 int128 i,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #38 31 int128 j,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #39 37 int128 i,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #40 38 int128 j,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #41 50 function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256);
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #42 54 int128 i,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #43 69 int128 i,
File: contracts-full/interfaces/curve/IEthStableMetaPool.sol #44 70 int128 j,
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #45 22 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #46 22 function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #47 24 function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #48 24 function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #49 26 function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #50 26 function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #51 35 function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256);
File: contracts-full/interfaces/curve/IStableSwap3Pool.sol #52 39 int128 i,
File: contracts-full/interfaces/IAaveLendingPool.sol #53 9 uint128 liquidityIndex;
File: contracts-full/interfaces/IAaveLendingPool.sol #54 11 uint128 variableBorrowIndex;
File: contracts-full/interfaces/IAaveLendingPool.sol #55 13 uint128 currentLiquidityRate;
File: contracts-full/interfaces/IAaveLendingPool.sol #56 15 uint128 currentVariableBorrowRate;
File: contracts-full/interfaces/IAaveLendingPool.sol #57 17 uint128 currentStableBorrowRate;
File: contracts-full/interfaces/IAaveLendingPool.sol #58 18 uint40 lastUpdateTimestamp;
File: contracts-full/interfaces/IAaveLendingPool.sol #59 26 uint8 id;
File: contracts-full/interfaces/IAaveLendingPool.sol #60 63 uint16 referralCode
File: contracts-full/interfaces/IAaveLendingPool.sol #61 83 uint16 referralCode
File: contracts-full/interfaces/IAaveLendingPool.sol #62 90 uint16 referralCode,
File: contracts-full/interfaces/ISelfPermit.sol #63 23 uint8 v,
File: contracts-full/interfaces/ISelfPermit.sol #64 45 uint8 v,
File: contracts-full/interfaces/ISelfPermit.sol #65 65 uint8 v,
File: contracts-full/interfaces/ISelfPermit.sol #66 88 uint8 v,
File: contracts-full/interfaces/external/aave/IWethGateway.sol #67 8 uint16 referralCode
File: contracts-full/interfaces/external/aave/IWethGateway.sol #68 28 uint16 referralCode
File: contracts-full/interfaces/external/aave/DataTypes.sol #69 9 uint128 liquidityIndex;
File: contracts-full/interfaces/external/aave/DataTypes.sol #70 11 uint128 variableBorrowIndex;
File: contracts-full/interfaces/external/aave/DataTypes.sol #71 13 uint128 currentLiquidityRate;
File: contracts-full/interfaces/external/aave/DataTypes.sol #72 15 uint128 currentVariableBorrowRate;
File: contracts-full/interfaces/external/aave/DataTypes.sol #73 17 uint128 currentStableBorrowRate;
File: contracts-full/interfaces/external/aave/DataTypes.sol #74 18 uint40 lastUpdateTimestamp;
File: contracts-full/interfaces/external/aave/DataTypes.sol #75 26 uint8 id;
File: contracts-full/interfaces/external/aave/ILendingPool.sol #76 21 uint16 indexed referral
File: contracts-full/interfaces/external/aave/ILendingPool.sol #77 49 uint16 indexed referral
File: contracts-full/interfaces/external/aave/ILendingPool.sol #78 99 uint16 referralCode
File: contracts-full/interfaces/external/aave/ILendingPool.sol #79 168 uint16 referralCode
File: contracts-full/interfaces/external/aave/ILendingPool.sol #80 206 uint16 referralCode,
File: contracts-full/interfaces/external/aave/ILendingPool.sol #81 296 uint16 referralCode
File: contracts-full/interfaces/external/aave/IStaticAToken.sol #82 16 uint8 v;
File: contracts-full/interfaces/external/aave/IStaticAToken.sol #83 30 uint16 referralCode,
File: contracts-full/interfaces/external/aave/IStaticAToken.sol #84 51 uint8 v,
File: contracts-full/interfaces/external/aave/IStaticAToken.sol #85 61 uint16 referralCode,
File: contracts-full/interfaces/external/uniswap/ISwapRouter.sol #86 12 uint24 fee;
File: contracts-full/interfaces/external/uniswap/ISwapRouter.sol #87 17 uint160 sqrtPriceLimitX96;
File: contracts-full/interfaces/external/uniswap/ISwapRouter.sol #88 45 uint24 fee;
File: contracts-full/interfaces/external/uniswap/ISwapRouter.sol #89 50 uint160 sqrtPriceLimitX96;
File: contracts-full/interfaces/vesper/IVesperPool.sol #90 26 uint8,
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #91 10 uint8 decimals;
File: contracts-full/interfaces/alchemist/IAlchemistV2State.sol #92 23 uint8 decimals;
File: contracts-full/interfaces/IERC20Metadata.sol #93 19 function decimals() external view returns (uint8);
File: contracts-full/libraries/SafeERC20.sol #94 29 function expectDecimals(address token) internal view returns (uint8) {
File: contracts-full/libraries/TokenUtils.sol #95 26 function expectDecimals(address token) internal view returns (uint8) {
File: contracts-full/AutoleverageBase.sol #96 19 int128 poolInputIndex;
File: contracts-full/AutoleverageBase.sol #97 20 int128 poolOutputIndex;
File: contracts-full/AutoleverageBase.sol #98 58 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal virtual returns (uint256 amountOut);
File: contracts-full/AutoleverageBase.sol #99 58 function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal virtual returns (uint256 amountOut);
File: contracts-full/AutoleverageBase.sol #100 77 int128 poolInputIndex,
File: contracts-full/AutoleverageBase.sol #101 78 int128 poolOutputIndex,
File: contracts-full/AlchemistV2.sol #102 321 uint8 tokenDecimals = TokenUtils.expectDecimals(underlyingToken);
File: contracts-full/AlchemistV2.sol #103 322 uint8 debtTokenDecimals = TokenUtils.expectDecimals(debtToken);
abi.encode()
is less efficient than abi.encodePacked()
File: contracts-full/AutoleverageBase.sol #1 102 bytes memory params = abi.encode(Details({ 103 pool: pool, 104 poolInputIndex: poolInputIndex, 105 poolOutputIndex: poolOutputIndex, 106 alchemist: alchemist, 107 yieldToken: yieldToken, 108 recipient: msg.sender, 109 targetDebt: targetDebt 110 }));
keccak256()
, should use immutable
rather than constant
See this issue for a detail description of the issue
File: contracts-full/AlchemicTokenV2Base.sol #1 22 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV2Base.sol #2 25 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/AlchemicTokenV2Base.sol #3 28 bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
File: contracts-full/TransmuterBuffer.sol #4 31 bytes32 public constant ADMIN = keccak256("ADMIN");
File: contracts-full/TransmuterBuffer.sol #5 34 bytes32 public constant KEEPER = keccak256("KEEPER");
File: contracts-full/AlchemicTokenV1.sol #6 22 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV1.sol #7 25 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/TransmuterV2.sol #8 99 bytes32 public constant ADMIN = keccak256("ADMIN");
File: contracts-full/TransmuterV2.sol #9 102 bytes32 public constant SENTINEL = keccak256("SENTINEL");
File: contracts-full/AlchemicTokenV2.sol #10 21 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV2.sol #11 24 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/AlchemicTokenV2.sol #12 27 bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
private
rather than public
for constants, saves gasIf needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table
File: contracts-full/AlchemicTokenV2Base.sol #1 22 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV2Base.sol #2 25 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/AlchemicTokenV2Base.sol #3 28 bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
File: contracts-full/AlchemicTokenV2Base.sol #4 31 uint256 public constant BPS = 10000;
File: contracts-full/TransmuterBuffer.sol #5 31 bytes32 public constant ADMIN = keccak256("ADMIN");
File: contracts-full/TransmuterBuffer.sol #6 34 bytes32 public constant KEEPER = keccak256("KEEPER");
File: contracts-full/AlchemicTokenV1.sol #7 22 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV1.sol #8 25 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/TransmuterV2.sol #9 99 bytes32 public constant ADMIN = keccak256("ADMIN");
File: contracts-full/TransmuterV2.sol #10 102 bytes32 public constant SENTINEL = keccak256("SENTINEL");
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #11 36 uint256 public immutable ethPoolIndex;
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #12 37 uint256 public immutable stEthPoolIndex;
File: contracts-full/gALCX.sol #13 15 uint public constant exchangeRatePrecision = 1e18;
File: contracts-full/AlchemicTokenV2.sol #14 21 bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
File: contracts-full/AlchemicTokenV2.sol #15 24 bytes32 public constant SENTINEL_ROLE = keccak256("SENTINEL");
File: contracts-full/AlchemicTokenV2.sol #16 27 bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
File: contracts-full/AlchemicTokenV2.sol #17 30 uint256 public constant BPS = 10000;
File: contracts-full/ThreePoolAssetManager.sol #18 211 uint256 public immutable convexPoolId;
File: contracts-full/libraries/Limiters.sol #19 12 uint256 constant public MAX_COOLDOWN_BLOCKS = 7200;
File: contracts-full/libraries/Limiters.sol #20 15 uint256 constant public FIXED_POINT_SCALAR = 1e18;
File: contracts-full/libraries/FixedPointMath.sol #21 9 uint256 public constant DECIMALS = 18;
File: contracts-full/libraries/FixedPointMath.sol #22 10 uint256 public constant ONE = 10**DECIMALS;
File: contracts-full/WETHGateway.sol #23 14 string public constant version = "2.1.0";
File: contracts-full/EthAssetManager.sol #24 179 uint256 public immutable convexPoolId;
File: contracts-full/AlchemistV2.sol #25 46 uint256 public constant BPS = 10000;
File: contracts-full/AlchemistV2.sol #26 51 uint256 public constant FIXED_POINT_SCALAR = 1e18;
SafeMath
once the solidity version is 0.8.0 or greaterVersion 0.8.0 introduces internal overflow checks, so using SafeMath
is redundant and adds overhead
File: contracts-full/TransmuterBuffer.sol #1 7 import "@openzeppelin/contracts/utils/math/SafeMath.sol";
require()
/revert()
checks should be refactored to a modifier or functionSaves deployment costs
File: contracts-full/gALCX.sol #1 107 require(success, "Transfer failed");
<x> * 2
is equivalent to <x> << 1
and <x> / 2
is the same as <x> >> 1
. The MUL
and DIV
opcodes cost 5 gas, whereas SHL
and SHR
only cost 3 gas
File: contracts-full/ThreePoolAssetManager.sol #1 355 if ((examineBalance = (v.maximum + v.minimum) / 2) == previousBalance) break;
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting. If the block is an empty if-statement block to avoid doing subsequent checks in the else-if/else conditions, the else-if/else conditions should be nested under the negation of the if-statement, because they involve different classes of checks, which may lead to the introduction of errors when the code is later modified (if(x){}else if(y){...}else{...}
=> if(!x){if(y){...}else{...}}
)
File: contracts-full/AutoleverageCurveMetapool.sol #1 20 function _maybeConvertCurveOutput(uint256 amountOut) internal override {}
File: contracts-full/AutoleverageCurveFactoryethpool.sol #2 17 receive() external payable {}
File: contracts-full/ThreePoolAssetManager.sol #3 737 function onERC20Received(address token, uint256 value) external { /* noop */ }
File: contracts-full/AutoleverageBase.sol #4 151 try IAlchemistV2(details.alchemist).mintFrom(details.recipient, details.targetDebt, address(this)) { 152 153 } catch {
File: contracts-full/EthAssetManager.sol #5 228 receive() external payable { }
File: contracts-full/EthAssetManager.sol #6 535 function onERC20Received(address token, uint256 value) external { /* noop */ }
revert()
/require()
strings to save deployment gasCustom errors are available from solidity version 0.8.4. The instances below match or exceed that version
File: contracts-full/StakingPools.sol #1 106 require(_governance != address(0), "StakingPools: governance address cannot be 0x0");
File: contracts-full/StakingPools.sol #2 114 require(msg.sender == governance, "StakingPools: only governance");
File: contracts-full/StakingPools.sol #3 124 require(_pendingGovernance != address(0), "StakingPools: pending governance address cannot be 0x0");
File: contracts-full/StakingPools.sol #4 131 require(msg.sender == pendingGovernance, "StakingPools: only pending governance");
File: contracts-full/StakingPools.sol #5 160 require(tokenPoolIds[_token] == 0, "StakingPools: token already has a pool");
File: contracts-full/StakingPools.sol #6 183 require(_rewardWeights.length == _pools.length(), "StakingPools: weights length mismatch");
File: contracts-full/AlchemicTokenV1.sol #7 51 require(whiteList[msg.sender], "AlTokenV1: Alchemist is not whitelisted");
File: contracts-full/AlchemicTokenV1.sol #8 57 require(hasRole(ADMIN_ROLE, msg.sender), "AlTokenV1: Only admin");
File: contracts-full/AlchemicTokenV1.sol #9 63 require(hasRole(SENTINEL_ROLE, msg.sender), "AlTokenV1: Only sentinel");
File: contracts-full/AlchemicTokenV1.sol #10 77 require(!blacklist[msg.sender], "AlUSD: Alchemist is blacklisted.");
File: contracts-full/AlchemicTokenV1.sol #11 78 require(!paused[msg.sender], "AlUSD: Currently paused.");
File: contracts-full/AlchemicTokenV1.sol #12 81 require(total <= ceiling[msg.sender], "AlUSD: Alchemist's ceiling was breached.");
File: contracts-full/gALCX.sol #13 33 require(msg.sender == owner, "Not owner");
File: contracts-full/gALCX.sol #14 90 require(success, "Transfer failed");
File: contracts-full/gALCX.sol #15 107 require(success, "Transfer failed");
File: contracts-full/libraries/LibFuse.sol #16 38 require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");
payable
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable
will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are
CALLVALUE
(2),DUP1
(3),ISZERO
(3),PUSH2
(3),JUMPI
(10),PUSH1
(3),DUP1
(3),REVERT
(0),JUMPDEST
(1),POP
(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
File: contracts-full/AlchemicTokenV2Base.sol #1 98 function setFlashFee(uint256 newFee) external onlyAdmin {
File: contracts-full/AlchemicTokenV2Base.sol #2 111 function mint(address recipient, uint256 amount) external onlyWhitelisted {
File: contracts-full/AlchemicTokenV2Base.sol #3 132 function setWhitelist(address minter, bool state) external onlyAdmin {
File: contracts-full/AlchemicTokenV2Base.sol #4 141 function setSentinel(address sentinel) external onlyAdmin {
File: contracts-full/AlchemicTokenV2Base.sol #5 151 function setCeiling(address minter, uint256 maximum) external onlyAdmin {
File: contracts-full/AlchemicTokenV2Base.sol #6 161 function pauseMinter(address minter, bool state) external onlySentinel {
File: contracts-full/AlchemicTokenV2Base.sol #7 189 function lowerHasMinted(uint256 amount) external onlyWhitelisted {
File: contracts-full/AlchemicTokenV2Base.sol #8 196 function setMaxFlashLoan(uint _maxFlashLoanAmount) external onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #9 178 function setWeights( 179 address weightToken, 180 address[] memory tokens, 181 uint256[] memory weights 182 ) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #10 212 function setSource(address source, bool flag) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #11 221 function setTransmuter(address underlyingToken, address newTransmuter) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #12 230 function setAlchemist(address _alchemist) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #13 251 function setAmo(address underlyingToken, address amo) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #14 257 function setDivertToAmo(address underlyingToken, bool divert) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #15 263 function registerAsset( 264 address underlyingToken, 265 address _transmuter 266 ) external override onlyAdmin {
File: contracts-full/TransmuterBuffer.sol #16 289 function setFlowRate(address underlyingToken, uint256 _flowRate) 290 external 291 override 292 onlyAdmin
File: contracts-full/TransmuterBuffer.sol #17 301 function onERC20Received(address underlyingToken, uint256 amount) 302 external 303 override 304 onlySource
File: contracts-full/TransmuterBuffer.sol #18 327 function exchange(address underlyingToken) external override onlyKeeper {
File: contracts-full/TransmuterBuffer.sol #19 332 function flushToAmo(address underlyingToken, uint256 amount) external override onlyKeeper {
File: contracts-full/TransmuterBuffer.sol #20 341 function withdraw( 342 address underlyingToken, 343 uint256 amount, 344 address recipient 345 ) external override onlyTransmuter(underlyingToken) {
File: contracts-full/TransmuterBuffer.sol #21 362 function withdrawFromAlchemist( 363 address yieldToken, 364 uint256 shares, 365 uint256 minimumAmountOut 366 ) external override onlyKeeper {
File: contracts-full/TransmuterBuffer.sol #22 400 function burnCredit() external override onlyKeeper {
File: contracts-full/TransmuterBuffer.sol #23 412 function depositFunds(address underlyingToken, uint256 amount) 413 external 414 override 415 onlyKeeper
File: contracts-full/StakingPools.sol #24 123 function setPendingGovernance(address _pendingGovernance) external onlyGovernance {
File: contracts-full/StakingPools.sol #25 144 function setRewardRate(uint256 _rewardRate) external onlyGovernance {
File: contracts-full/StakingPools.sol #26 159 function createPool(IERC20 _token) external onlyGovernance returns (uint256) {
File: contracts-full/StakingPools.sol #27 182 function setRewardWeights(uint256[] calldata _rewardWeights) external onlyGovernance {
File: contracts-full/AlchemicTokenV1.sol #28 76 function mint(address recipient, uint256 amount) external onlyWhitelisted {
File: contracts-full/AlchemicTokenV1.sol #29 92 function setWhitelist(address minter, bool state) external onlyAdmin {
File: contracts-full/AlchemicTokenV1.sol #30 101 function setSentinel(address sentinel) external onlyAdmin {
File: contracts-full/AlchemicTokenV1.sol #31 110 function setBlacklist(address minter) external onlySentinel {
File: contracts-full/AlchemicTokenV1.sol #32 120 function pauseAlchemist(address alchemist, bool state) external onlySentinel {
File: contracts-full/AlchemicTokenV1.sol #33 131 function setCeiling(address minter, uint256 maximum) external onlyAdmin {
File: contracts-full/AlchemicTokenV1.sol #34 159 function lowerHasMinted(uint256 amount) public onlyWhitelisted {
File: contracts-full/TransmuterV2.sol #35 201 function setPause(bool pauseState) external onlySentinelOrAdmin {
File: contracts-full/TransmuterV2.sol #36 250 function exchange(uint256 amount) external override nonReentrant onlyBuffer notPaused {
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #37 87 function wrap( 88 uint256 amount, 89 address recipient 90 ) external lock onlyAlchemist returns (uint256) {
File: contracts-full/adapters/lido/WstETHAdapterV1.sol #38 115 function unwrap( 116 uint256 amount, 117 address recipient 118 ) external lock onlyAlchemist returns (uint256) {
File: contracts-full/adapters/rocket/RETHAdapterV1.sol #39 64 function wrap( 65 uint256 amount, 66 address recipient 67 ) external onlyAlchemist returns (uint256) {
File: contracts-full/adapters/rocket/RETHAdapterV1.sol #40 83 function unwrap( 84 uint256 amount, 85 address recipient 86 ) external lock onlyAlchemist returns (uint256) {
File: contracts-full/adapters/vesper/VesperAdapterV1.sol #41 56 function wrap( 57 uint256 amount, 58 address recipient 59 ) external onlyAlchemist returns (uint256) {
File: contracts-full/adapters/vesper/VesperAdapterV1.sol #42 80 function unwrap( 81 uint256 amount, 82 address recipient 83 ) external lock onlyAlchemist returns (uint256) {
File: contracts-full/adapters/fuse/FuseTokenAdapterV1.sol #43 66 function wrap( 67 uint256 amount, 68 address recipient 69 ) external onlyAlchemist returns (uint256) {
File: contracts-full/adapters/fuse/FuseTokenAdapterV1.sol #44 89 function unwrap( 90 uint256 amount, 91 address recipient 92 ) external lock onlyAlchemist returns (uint256) {
File: contracts-full/gALCX.sol #45 39 function transferOwnership(address _owner) external onlyOwner {
File: contracts-full/gALCX.sol #46 46 function migrateSource(address _pools, uint _poolId) external onlyOwner {
File: contracts-full/AlchemicTokenV2.sol #47 92 function setFlashFee(uint256 newFee) external onlyAdmin {
File: contracts-full/AlchemicTokenV2.sol #48 105 function mint(address recipient, uint256 amount) external onlyWhitelisted {
File: contracts-full/AlchemicTokenV2.sol #49 119 function setWhitelist(address minter, bool state) external onlyAdmin {
File: contracts-full/AlchemicTokenV2.sol #50 128 function setSentinel(address sentinel) external onlyAdmin {
File: contracts-full/AlchemicTokenV2.sol #51 138 function pauseMinter(address minter, bool state) external onlySentinel {
File: contracts-full/AlchemicTokenV2.sol #52 164 function setMaxFlashLoan(uint _maxFlashLoanAmount) external onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #53 445 function setPendingAdmin(address value) external onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #54 476 function setOperator(address value) external onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #55 484 function setRewardReceiver(address value) external onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #56 492 function setTransmuterBuffer(address value) external onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #57 504 function setThreePoolSlippage(uint256 value) external onlyOperator {
File: contracts-full/ThreePoolAssetManager.sol #58 519 function setMetaPoolSlippage(uint256 value) external onlyOperator {
File: contracts-full/ThreePoolAssetManager.sol #59 532 function mintThreePoolTokens( 533 uint256[NUM_STABLE_COINS] calldata amounts 534 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/ThreePoolAssetManager.sol #60 544 function mintThreePoolTokens( 545 ThreePoolAsset asset, 546 uint256 amount 547 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/ThreePoolAssetManager.sol #61 557 function burnThreePoolTokens( 558 ThreePoolAsset asset, 559 uint256 amount 560 ) external lock onlyOperator returns (uint256 withdrawn) {
File: contracts-full/ThreePoolAssetManager.sol #62 569 function mintMetaPoolTokens( 570 uint256[NUM_META_COINS] calldata amounts 571 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/ThreePoolAssetManager.sol #63 581 function mintMetaPoolTokens( 582 MetaPoolAsset asset, 583 uint256 amount 584 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/ThreePoolAssetManager.sol #64 594 function burnMetaPoolTokens( 595 MetaPoolAsset asset, 596 uint256 amount 597 ) external lock onlyOperator returns (uint256 withdrawn) {
File: contracts-full/ThreePoolAssetManager.sol #65 606 function depositMetaPoolTokens( 607 uint256 amount 608 ) external lock onlyOperator returns (bool success) {
File: contracts-full/ThreePoolAssetManager.sol #66 617 function withdrawMetaPoolTokens( 618 uint256 amount 619 ) external lock onlyOperator returns (bool success) {
File: contracts-full/ThreePoolAssetManager.sol #67 626 function claimRewards() external lock onlyOperator returns (bool success) {
File: contracts-full/ThreePoolAssetManager.sol #68 647 function flush( 648 uint256[NUM_STABLE_COINS] calldata amounts 649 ) external lock onlyOperator returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #69 674 function flush( 675 ThreePoolAsset asset, 676 uint256 amount 677 ) external lock onlyOperator returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #70 702 function recall( 703 ThreePoolAsset asset, 704 uint256 amount 705 ) external lock onlyOperator returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #71 717 function reclaimThreePoolAsset(ThreePoolAsset asset, uint256 amount) public lock onlyAdmin {
File: contracts-full/ThreePoolAssetManager.sol #72 730 function sweep(address token, uint256 amount) external lock onlyAdmin {
File: contracts-full/CrossChainCanonicalBase.sol #73 133 function toggleExchanges() external onlyOwner {
File: contracts-full/CrossChainCanonicalBase.sol #74 139 function addBridgeToken(address bridgeTokenAddress) external onlyOwner {
File: contracts-full/CrossChainCanonicalBase.sol #75 156 function toggleBridgeToken(address bridgeTokenAddress, bool enabled) external onlyOwner {
File: contracts-full/CrossChainCanonicalBase.sol #76 163 function setSwapFees(address bridgeTokenAddress, uint256 _bridgeToCanonical, uint256 _canonicalToOld) external onlyOwner {
File: contracts-full/CrossChainCanonicalBase.sol #77 169 function toggleFeesForAddress(address targetAddress) external onlyOwner {
File: contracts-full/CrossChainCanonicalBase.sol #78 173 function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
File: contracts-full/WETHGateway.sol #79 35 function refreshAllowance(address alchemist) external onlyOwner {
File: contracts-full/TransmuterConduit.sol #80 34 function distribute(address origin, uint256 amount) external onlySource() {
File: contracts-full/EthAssetManager.sol #81 293 function setPendingAdmin(address value) external onlyAdmin {
File: contracts-full/EthAssetManager.sol #82 324 function setOperator(address value) external onlyAdmin {
File: contracts-full/EthAssetManager.sol #83 332 function setRewardReceiver(address value) external onlyAdmin {
File: contracts-full/EthAssetManager.sol #84 340 function setTransmuterBuffer(address value) external onlyAdmin {
File: contracts-full/EthAssetManager.sol #85 352 function setMetaPoolSlippage(uint256 value) external onlyOperator {
File: contracts-full/EthAssetManager.sol #86 365 function mintMetaPoolTokens( 366 uint256[NUM_META_COINS] calldata amounts 367 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/EthAssetManager.sol #87 377 function mintMetaPoolTokens( 378 MetaPoolAsset asset, 379 uint256 amount 380 ) external lock onlyOperator returns (uint256 minted) {
File: contracts-full/EthAssetManager.sol #88 390 function burnMetaPoolTokens( 391 MetaPoolAsset asset, 392 uint256 amount 393 ) external lock onlyOperator returns (uint256 withdrawn) {
File: contracts-full/EthAssetManager.sol #89 402 function depositMetaPoolTokens( 403 uint256 amount 404 ) external lock onlyOperator returns (bool success) {
File: contracts-full/EthAssetManager.sol #90 413 function withdrawMetaPoolTokens( 414 uint256 amount 415 ) external lock onlyOperator returns (bool success) {
File: contracts-full/EthAssetManager.sol #91 422 function claimRewards() external lock onlyOperator returns (bool success) {
File: contracts-full/EthAssetManager.sol #92 442 function flush( 443 uint256[NUM_META_COINS] calldata amounts 444 ) external lock onlyOperator returns (uint256) {
File: contracts-full/EthAssetManager.sol #93 463 function flush( 464 MetaPoolAsset asset, 465 uint256 amount 466 ) external lock onlyOperator returns (uint256) {
File: contracts-full/EthAssetManager.sol #94 484 function recall(uint256 amount) external lock onlyOperator returns (uint256) {
File: contracts-full/EthAssetManager.sol #95 494 function reclaimEth(uint256 amount) public lock onlyAdmin {
File: contracts-full/EthAssetManager.sol #96 509 function sweepToken(address token, uint256 amount) external lock onlyAdmin {
File: contracts-full/EthAssetManager.sol #97 519 function sweepEth( 520 uint256 amount 521 ) external lock onlyAdmin returns (bytes memory result) {
public
functions not called by the contract should be declared external
insteadContracts are allowed to override their parents' functions and change the visibility from external
to public
and can save gas by doing so.
File: contracts-full/CrossChainCanonicalAlchemicTokenV2.sol #1 8 function initialize( 9 string memory name, 10 string memory symbol, 11 address[] memory _bridgeTokens 12 ) public initializer {
File: contracts-full/AlchemicTokenV1.sol #2 138 function burn(uint256 amount) public {
File: contracts-full/AlchemicTokenV1.sol #3 148 function burnFrom(address owner, uint256 amount) public {
File: contracts-full/AlchemicTokenV1.sol #4 159 function lowerHasMinted(uint256 amount) public onlyWhitelisted {
File: contracts-full/CrossChainCanonicalGALCX.sol #5 7 function initialize( 8 string memory name, 9 string memory symbol, 10 address[] memory _bridgeTokens 11 ) public initializer {
File: contracts-full/ThreePoolAssetManager.sol #6 298 function exchangeRate(ThreePoolAsset asset) public view returns (uint256) {
File: contracts-full/ThreePoolAssetManager.sol #7 330 function calculateRebalance( 331 MetaPoolAsset rebalanceAsset, 332 ThreePoolAsset targetExchangeAsset, 333 uint256 targetExchangeRate 334 ) public view returns (uint256 delta, bool add) {
File: contracts-full/ThreePoolAssetManager.sol #8 408 function claimableRewards() public view returns (uint256 amountCurve, uint256 amountConvex) {
File: contracts-full/ThreePoolAssetManager.sol #9 717 function reclaimThreePoolAsset(ThreePoolAsset asset, uint256 amount) public lock onlyAdmin {
File: contracts-full/EthAssetManager.sol #10 253 function exchangeRate() public view returns (uint256) {
File: contracts-full/EthAssetManager.sol #11 269 function claimableRewards() public view returns (uint256 amountCurve, uint256 amountConvex) {
File: contracts-full/EthAssetManager.sol #12 494 function reclaimEth(uint256 amount) public lock onlyAdmin {
#0 - liveactionllama
2022-05-06T20:47:05Z
Warden created this issue as a placeholder, because their submission was too large for the contest form. They then emailed their md file to our team on 05/06/2022. I've updated this issue with their md file content.
#1 - 0xfoobar
2022-05-30T07:11:25Z
Incredibly comprehensive, great work with the explanations and detailed line number links