Source Code
Latest 19 from a total of 19 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Mint Chamber Fro... | 19592114 | 700 days ago | IN | 7.13496718 ETH | 0.02342354 | ||||
| Mint Chamber Fro... | 19592106 | 700 days ago | IN | 6.98923021 ETH | 0.01337924 | ||||
| Mint From Native... | 19536035 | 708 days ago | IN | 1.23134611 ETH | 0.00164385 | ||||
| Mint Chamber Fro... | 19529334 | 709 days ago | IN | 8.58339887 ETH | 0.03186411 | ||||
| Mint Chamber Fro... | 19525700 | 710 days ago | IN | 13.05283485 ETH | 0.08200273 | ||||
| Redeem Chamber T... | 19525695 | 710 days ago | IN | 0 ETH | 0.02829024 | ||||
| Mint Chamber Fro... | 19493701 | 714 days ago | IN | 6.93801385 ETH | 0.01423048 | ||||
| Mint Chamber Fro... | 19440954 | 722 days ago | IN | 8.16926549 ETH | 0.14739726 | ||||
| Mint Chamber Fro... | 19435819 | 722 days ago | IN | 8.14294117 ETH | 0.07266565 | ||||
| Mint Chamber Fro... | 19384292 | 730 days ago | IN | 13.86858816 ETH | 0.0502915 | ||||
| Mint Chamber Fro... | 19292795 | 742 days ago | IN | 10.61641841 ETH | 0.01986029 | ||||
| Mint Chamber Fro... | 19292001 | 742 days ago | IN | 7.71529949 ETH | 0.01942336 | ||||
| Mint Chamber Fro... | 19291974 | 742 days ago | IN | 7.75506201 ETH | 0.02088323 | ||||
| Mint Chamber Fro... | 19241453 | 750 days ago | IN | 12.77011435 ETH | 0.02158368 | ||||
| Mint Chamber Fro... | 19093854 | 770 days ago | IN | 16.13294035 ETH | 0.00692494 | ||||
| Mint Chamber Fro... | 19021133 | 780 days ago | IN | 12.12895718 ETH | 0.02647744 | ||||
| Mint Chamber Fro... | 18971642 | 787 days ago | IN | 21.41152417 ETH | 0.01262209 | ||||
| Mint Chamber Fro... | 18886798 | 799 days ago | IN | 7.89785079 ETH | 0.01296797 | ||||
| Transfer Ownersh... | 16743664 | 1100 days ago | IN | 0 ETH | 0.00067785 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 19664018 | 690 days ago | 0.02816276 ETH | ||||
| Transfer | 19664018 | 690 days ago | 0.02816276 ETH | ||||
| Deposit | 19664018 | 690 days ago | 6.51759926 ETH | ||||
| Mint Chamber Fro... | 19664018 | 690 days ago | 6.51759926 ETH | ||||
| Transfer | 19663759 | 690 days ago | 0.00335575 ETH | ||||
| Transfer | 19663759 | 690 days ago | 0.00335575 ETH | ||||
| Deposit | 19663759 | 690 days ago | 9.83010157 ETH | ||||
| Mint Chamber Fro... | 19663759 | 690 days ago | 9.83010157 ETH | ||||
| Transfer | 19663720 | 690 days ago | 16.10444417 ETH | ||||
| Transfer | 19663720 | 690 days ago | 16.10444417 ETH | ||||
| Transfer | 19592114 | 700 days ago | 7 wei | ||||
| Transfer | 19592114 | 700 days ago | 7 wei | ||||
| Deposit | 19592114 | 700 days ago | 7.13496718 ETH | ||||
| Transfer | 19592106 | 700 days ago | 0.01012173 ETH | ||||
| Transfer | 19592106 | 700 days ago | 0.01012173 ETH | ||||
| Deposit | 19592106 | 700 days ago | 6.98923021 ETH | ||||
| Transfer | 19529334 | 709 days ago | 0.03629366 ETH | ||||
| Transfer | 19529334 | 709 days ago | 0.03629366 ETH | ||||
| Deposit | 19529334 | 709 days ago | 8.58339887 ETH | ||||
| Transfer | 19525700 | 710 days ago | 0.05722359 ETH | ||||
| Transfer | 19525700 | 710 days ago | 0.05722359 ETH | ||||
| Deposit | 19525700 | 710 days ago | 13.05283485 ETH | ||||
| Transfer | 19525695 | 710 days ago | 15.92396526 ETH | ||||
| Transfer | 19525695 | 710 days ago | 15.92396526 ETH | ||||
| Transfer | 19493701 | 714 days ago | 9 wei |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TradeIssuerV2
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/**
* SPDX-License-Identifier: Apache License 2.0
*
* Copyright 2021 Index Cooperative
* Copyright 2023 Smash Works Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE
*
* This is a modified code from Index Cooperative Inc. found at
*
* https://github.com/IndexCoop/index-coop-smart-contracts
*
* All changes made by Smash Works Inc. are described and documented at
*
* https://docs.arch.finance/chambers
*
*
* %@@@@@
* @@@@@@@@@@@
* #@@@@@ @@@ @@ @@
* @@@@@@ @@@ @@@@ @@
* @@@@@@ @@ @@ @@ @@@@@ @@@@@ @@@*@@
* .@@@@@ @@@ @@@@@@@@ @@ @@ @@ @@
* @@@@@( ((((( @@@ @@@ @@ @@@@@ @@ @@
* @@@@@@ (((((((
* @@@@@#(((((((
* @@@@@(((((
* @@@((
*/
pragma solidity ^0.8.17.0;
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IChamber} from "chambers/interfaces/IChamber.sol";
import {IChamberGod} from "chambers/interfaces/IChamberGod.sol";
import {IIssuerWizard} from "chambers/interfaces/IIssuerWizard.sol";
import {ITradeIssuerV2} from "./interfaces/ITradeIssuerV2.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "solmate/utils/ReentrancyGuard.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {WETH} from "solmate/tokens/WETH.sol";
contract TradeIssuerV2 is ITradeIssuerV2, Ownable, ReentrancyGuard {
/*//////////////////////////////////////////////////////////////
LIBRARIES
//////////////////////////////////////////////////////////////*/
using Address for address;
using Address for address payable;
using EnumerableSet for EnumerableSet.AddressSet;
using SafeERC20 for IERC20;
/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
EnumerableSet.AddressSet private allowedTargets;
address public immutable wrappedNativeToken;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/**
* @param _wrappedNativeToken Wrapped network native token
*/
constructor(address _wrappedNativeToken) {
wrappedNativeToken = _wrappedNativeToken;
}
receive() external payable {}
/*//////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* Returns an array of the allowed targets for the trade issuer
*
* @return address[] An address array containing the allowed targets
*/
function getAllowedTargets() external view returns (address[] memory) {
return allowedTargets.values();
}
/**
* Checks if the address is an allowed target
*
* @param _target The address to check
*
* @return bool True if the address is a valid target
*/
function isAllowedTarget(address _target) public view returns (bool) {
return allowedTargets.contains(_target);
}
/**
* Allows the trade issuer to perform low level calls to the specified target
*
* @param _target The address of the target to allow
*/
function addTarget(address _target) external onlyOwner nonReentrant {
if (_target == address(0)) {
revert InvalidTarget(_target);
}
if (isAllowedTarget(address(_target))) revert TargetAlreadyAllowed();
if (!allowedTargets.add(_target)) revert CannotAllowTarget();
emit AllowedTargetAdded(_target);
}
/**
* Removes the ability to perform low level calls to the target
*
* @param _target The address of the target to remove
*/
function removeTarget(address _target) external onlyOwner nonReentrant {
if (!isAllowedTarget(_target)) {
revert InvalidTarget(_target);
}
if (!allowedTargets.remove(_target)) revert CannotRemoveTarget();
emit AllowedTargetRemoved(_target);
}
/**
* Transfer the total balance of the specified stucked token to the owner address
*
* @param _tokenToWithdraw The ERC20 token address to withdraw
*/
function transferERC20ToOwner(address _tokenToWithdraw) external onlyOwner nonReentrant {
if (IERC20(_tokenToWithdraw).balanceOf(address(this)) < 1) revert ZeroBalanceAsset();
IERC20(_tokenToWithdraw).safeTransfer(
owner(), IERC20(_tokenToWithdraw).balanceOf(address(this))
);
}
/**
* Transfer all stucked Ether to the owner of the contract
*/
function transferEthToOwner() external onlyOwner nonReentrant {
if (address(this).balance < 1) revert ZeroBalanceAsset();
payable(owner()).transfer(address(this).balance);
}
/**
* Mints the specified amount of chamber token and sends them to the msg.sender using an ERC20
* token as input. Unspent baseToken is also transferred back to the sender.
*
* @param _chamber Chamber address.
* @param _issuerWizard Issuer wizard that'll be called for mint.
* @param _baseToken The token that will be used to get the underlying assets.
* @param _maxPayAmount The maximum amount of the baseToken to be used for the mint.
* @param _mintAmount Chamber tokens amount to mint.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*
* @return baseTokenUsed Total amount of the base token used for the mint.
*
*/
function mintChamberFromToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
IERC20 _baseToken,
uint256 _maxPayAmount,
uint256 _mintAmount
) external nonReentrant returns (uint256 baseTokenUsed) {
if (_mintAmount == 0) revert ZeroChamberAmount();
_baseToken.safeTransferFrom(msg.sender, address(this), _maxPayAmount);
baseTokenUsed = _mintChamber(
_chamber, IERC20(_baseToken), _issuerWizard, _mintAmount, _contractCallInstructions
);
if (_maxPayAmount < baseTokenUsed) revert OversoldBaseToken();
uint256 remainingBaseToken = _maxPayAmount - baseTokenUsed;
_baseToken.safeTransfer(msg.sender, remainingBaseToken);
IERC20(address(_chamber)).safeTransfer(msg.sender, _mintAmount);
emit TradeIssuerTokenMinted(
address(_chamber), msg.sender, address(_baseToken), baseTokenUsed, _mintAmount
);
return baseTokenUsed;
}
/**
* Mints the specified amount of chamber token and sends them to the msg.sender using the network
* native token as input. Unspent native token is also transferred back to the sender.
*
* @param _chamber Chamber address.
* @param _issuerWizard Issuer wizard that'll be called for mint.
* @param _mintAmount Chamber tokens amount to mint.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*
* @return wrappedNativeTokenUsed Total amount of the wrapped native token used for the mint.
*
*/
function mintChamberFromNativeToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
uint256 _mintAmount
) external payable nonReentrant returns (uint256 wrappedNativeTokenUsed) {
if (_mintAmount == 0) revert ZeroChamberAmount();
if (msg.value == 0) revert ZeroNativeTokenSent();
WETH(payable(wrappedNativeToken)).deposit{value: msg.value}();
wrappedNativeTokenUsed = _mintChamber(
_chamber,
IERC20(wrappedNativeToken),
_issuerWizard,
_mintAmount,
_contractCallInstructions
);
if (msg.value < wrappedNativeTokenUsed) revert OversoldBaseToken();
uint256 remainingWrappedNativeToken = msg.value - wrappedNativeTokenUsed;
WETH(payable(wrappedNativeToken)).withdraw(remainingWrappedNativeToken);
payable(msg.sender).sendValue(remainingWrappedNativeToken);
IERC20(address(_chamber)).safeTransfer(msg.sender, _mintAmount);
emit TradeIssuerTokenMinted(
address(_chamber),
msg.sender,
address(wrappedNativeToken),
wrappedNativeTokenUsed,
_mintAmount
);
return wrappedNativeTokenUsed;
}
/**
* Redeems the specified amount of chamber token for the required baseToken and sends it to the
* msg.sender.
*
* @param _chamber Chamber address.
* @param _issuerWizard Issuer wizard that'll be called for redeem.
* @param _baseToken The token that it will be sent to the msg.sender.
* @param _minReceiveAmount The minimum amount of the baseToken to be received.
* @param _redeemAmount Chamber tokens amount to redeem.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*
* @return baseTokenReturned Total baseToken amount sent to the msg.sender.
*
*/
function redeemChamberToToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
IERC20 _baseToken,
uint256 _minReceiveAmount,
uint256 _redeemAmount
) external nonReentrant returns (uint256 baseTokenReturned) {
if (_redeemAmount == 0) revert ZeroChamberAmount();
IERC20(address(_chamber)).safeTransferFrom(msg.sender, address(this), _redeemAmount);
baseTokenReturned = _redeemChamber(
_chamber, _baseToken, _issuerWizard, _redeemAmount, _contractCallInstructions
);
if (baseTokenReturned < _minReceiveAmount) {
revert RedeemedForLessTokens();
}
_baseToken.safeTransfer(msg.sender, baseTokenReturned);
emit TradeIssuerTokenRedeemed(
address(_chamber), msg.sender, address(_baseToken), baseTokenReturned, _redeemAmount
);
return baseTokenReturned;
}
/**
* Redeems the specified amount of chamber token for the network's native token and sends it to the
* msg.sender.
*
* @param _chamber Chamber address.
* @param _issuerWizard Issuer wizard that'll be called for redeem.
* @param _minReceiveAmount The minimum amount of the baseToken to be received.
* @param _redeemAmount Chamber tokens amount to redeem.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*
* @return wrappedNativeTokenReturned Total native token amount sent to the msg.sender.
*
*/
function redeemChamberToNativeToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
uint256 _minReceiveAmount,
uint256 _redeemAmount
) external nonReentrant returns (uint256 wrappedNativeTokenReturned) {
if (_redeemAmount == 0) revert ZeroChamberAmount();
IERC20(address(_chamber)).safeTransferFrom(msg.sender, address(this), _redeemAmount);
wrappedNativeTokenReturned = _redeemChamber(
_chamber,
IERC20(wrappedNativeToken),
_issuerWizard,
_redeemAmount,
_contractCallInstructions
);
if (wrappedNativeTokenReturned < _minReceiveAmount) {
revert RedeemedForLessTokens();
}
WETH(payable(wrappedNativeToken)).withdraw(wrappedNativeTokenReturned);
payable(msg.sender).sendValue(wrappedNativeTokenReturned);
emit TradeIssuerTokenRedeemed(
address(_chamber),
msg.sender,
address(wrappedNativeToken),
wrappedNativeTokenReturned,
_redeemAmount
);
return wrappedNativeTokenReturned;
}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* Internal function in charge of the generic mint. The main objective is to get the chamber tokens.
*
* @param _chamber Chamber address.
* @param _baseToken The token that will be used to get the underlying assets.
* @param _issuerWizard Issuer wizard that'll be called for mint.
* @param _mintAmount Chamber tokens amount to mint.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*
* @return baseTokenUsed Total amount of the base token used for the mint.
*
*/
function _mintChamber(
IChamber _chamber,
IERC20 _baseToken,
IIssuerWizard _issuerWizard,
uint256 _mintAmount,
ContractCallInstruction[] memory _contractCallInstructions
) internal returns (uint256 baseTokenUsed) {
uint256 baseTokenBalanceBefore = _baseToken.balanceOf(address(this));
_executeInstructions(_contractCallInstructions);
_checkAndIncreaseAllowanceOfConstituents(_chamber, _issuerWizard, _mintAmount);
_issuerWizard.issue(_chamber, _mintAmount);
baseTokenUsed = baseTokenBalanceBefore - _baseToken.balanceOf(address(this));
return baseTokenUsed;
}
/**
* Internal function in charge of the generic redeem. The main objective is to get the base token
* from the chamber token.
*
* @param _chamber Chamber address.
* @param _baseToken The token that will be used to get the underlying assets.
* @param _issuerWizard Issuer wizard that'll be called for redeem.
* @param _redeemAmount Chamber tokens amount to redeem.
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the _baseToken assets.
*
* @return totalBaseTokenReturned Total amount of the base that will be sent to the msg.sender.
*
*/
function _redeemChamber(
IChamber _chamber,
IERC20 _baseToken,
IIssuerWizard _issuerWizard,
uint256 _redeemAmount,
ContractCallInstruction[] memory _contractCallInstructions
) internal returns (uint256 totalBaseTokenReturned) {
uint256 baseTokenBalanceBefore = _baseToken.balanceOf(address(this));
_issuerWizard.redeem(_chamber, _redeemAmount);
_executeInstructions(_contractCallInstructions);
totalBaseTokenReturned = _baseToken.balanceOf(address(this)) - baseTokenBalanceBefore;
return totalBaseTokenReturned;
}
/**
* Executes the array of instructions and verifies that the correct amount of each token
* from the instruction is purchased.
*
* @param _contractCallInstructions Instruction array that will be executed in order to get
* the underlying assets.
*/
function _executeInstructions(ContractCallInstruction[] memory _contractCallInstructions)
internal
{
for (uint256 i = 0; i < _contractCallInstructions.length; i++) {
ContractCallInstruction memory currentInstruction = _contractCallInstructions[i];
uint256 buyTokenBalanceBefore = currentInstruction._buyToken.balanceOf(address(this));
_checkAndIncreaseAllowance(
address(currentInstruction._sellToken),
currentInstruction._allowanceTarget,
currentInstruction._sellAmount
);
_fillQuote(currentInstruction._target, currentInstruction._callData);
uint256 buyTokenAmountBought =
currentInstruction._buyToken.balanceOf(address(this)) - buyTokenBalanceBefore;
if (currentInstruction._minBuyAmount > buyTokenAmountBought) {
revert UnderboughtAsset(
currentInstruction._buyToken, currentInstruction._minBuyAmount
);
}
}
}
/**
* Execute a contract call
*
* @param _callData CallData to be executed on a allowed Target
*
* @return response Response from the low-level call
*/
function _fillQuote(address _target, bytes memory _callData)
internal
returns (bytes memory response)
{
if (!isAllowedTarget(_target)) revert InvalidTarget(_target);
response = _target.functionCall(_callData);
if (response.length == 0) revert LowLevelFunctionCallFailed();
return (response);
}
/**
* Checks the allowance for issuance of a chamberToken, if allowance is not enough it's increased to max.
*
* @param _chamber Chamber token address for mint.
* @param _issuerWizard Issuer wizard used at _chamber.
* @param _mintAmount Amount of the chamber token to mint.
*/
function _checkAndIncreaseAllowanceOfConstituents(
IChamber _chamber,
IIssuerWizard _issuerWizard,
uint256 _mintAmount
) internal {
(address[] memory requiredConstituents, uint256[] memory requiredConstituentsQuantities) =
_issuerWizard.getConstituentsQuantitiesForIssuance(_chamber, _mintAmount);
for (uint256 i = 0; i < requiredConstituents.length; i++) {
if (
IERC20(requiredConstituents[i]).balanceOf(address(this))
< requiredConstituentsQuantities[i]
) {
revert UnderboughtConstituent(
IERC20(requiredConstituents[i]), requiredConstituentsQuantities[i]
);
}
_checkAndIncreaseAllowance(
requiredConstituents[i], address(_issuerWizard), requiredConstituentsQuantities[i]
);
}
}
/**
* For the specified token and amount, checks the allowance between the TraderIssuer and _target.
* If not enough, it sets the maximum.
*
* @param _tokenAddress Address of the token that will be used.
* @param _target Target address of the allowance.
* @param _requiredAmount Required allowance for the operation.
*/
function _checkAndIncreaseAllowance(
address _tokenAddress,
address _target,
uint256 _requiredAmount
) internal {
if (_requiredAmount == 0) revert ZeroRequiredAmount();
uint256 currentAllowance = IERC20(_tokenAddress).allowance(address(this), _target);
if (currentAllowance < _requiredAmount) {
IERC20(_tokenAddress).safeIncreaseAllowance(
_target, type(uint256).max - currentAllowance
);
}
}
}/**
* SPDX-License-Identifier: Apache License 2.0
*
* Copyright 2018 Set Labs Inc.
* Copyright 2022 Smash Works Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE
*
* This is a modified code from Set Labs Inc. found at
*
* https://github.com/SetProtocol/set-protocol-contracts
*
* All changes made by Smash Works Inc. are described and documented at
*
* https://docs.arch.finance/chambers
*
*
* %@@@@@
* @@@@@@@@@@@
* #@@@@@ @@@ @@ @@
* @@@@@@ @@@ @@@@ @@
* @@@@@@ @@ @@ @@ @@@@@ @@@@@ @@@*@@
* .@@@@@ @@@ @@@@@@@@ @@ @@ @@ @@
* @@@@@( ((((( @@@ @@@ @@ @@@@@ @@ @@
* @@@@@@ (((((((
* @@@@@#(((((((
* @@@@@(((((
* @@@((
*/
pragma solidity ^0.8.17.0;
interface IChamber {
/*//////////////////////////////////////////////////////////////
ENUMS
//////////////////////////////////////////////////////////////*/
enum ChamberState {
LOCKED,
UNLOCKED
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event ManagerAdded(address indexed _manager);
event ManagerRemoved(address indexed _manager);
event ConstituentAdded(address indexed _constituent);
event ConstituentRemoved(address indexed _constituent);
event WizardAdded(address indexed _wizard);
event WizardRemoved(address indexed _wizard);
event AllowedContractAdded(address indexed _allowedContract);
event AllowedContractRemoved(address indexed _allowedContract);
/*//////////////////////////////////////////////////////////////
CHAMBER MANAGEMENT
//////////////////////////////////////////////////////////////*/
function addConstituent(address _constituent) external;
function removeConstituent(address _constituent) external;
function isManager(address _manager) external view returns (bool);
function isWizard(address _wizard) external view returns (bool);
function isConstituent(address _constituent) external view returns (bool);
function addManager(address _manager) external;
function removeManager(address _manager) external;
function addWizard(address _wizard) external;
function removeWizard(address _wizard) external;
function getConstituentsAddresses() external view returns (address[] memory);
function getQuantities() external view returns (uint256[] memory);
function getConstituentQuantity(address _constituent) external view returns (uint256);
function getWizards() external view returns (address[] memory);
function getManagers() external view returns (address[] memory);
function getAllowedContracts() external view returns (address[] memory);
function mint(address _recipient, uint256 _quantity) external;
function burn(address _from, uint256 _quantity) external;
function withdrawTo(address _constituent, address _recipient, uint256 _quantity) external;
function updateQuantities() external;
function lockChamber() external;
function unlockChamber() external;
function addAllowedContract(address target) external;
function removeAllowedContract(address target) external;
function isAllowedContract(address _target) external returns (bool);
function executeTrade(
address _sellToken,
uint256 _sellQuantity,
address _buyToken,
uint256 _minBuyQuantity,
bytes memory _data,
address payable _target,
address _allowanceTarget
) external returns (uint256 tokenAmountBought);
}/**
* SPDX-License-Identifier: Apache License 2.0
*
* Copyright 2018 Set Labs Inc.
* Copyright 2022 Smash Works Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE
*
* This is a modified code from Set Labs Inc. found at
*
* https://github.com/SetProtocol/set-protocol-contracts
*
* All changes made by Smash Works Inc. are described and documented at
*
* https://docs.arch.finance/chambers
*
*
* %@@@@@
* @@@@@@@@@@@
* #@@@@@ @@@ @@ @@
* @@@@@@ @@@ @@@@ @@
* @@@@@@ @@ @@ @@ @@@@@ @@@@@ @@@*@@
* .@@@@@ @@@ @@@@@@@@ @@ @@ @@ @@
* @@@@@( ((((( @@@ @@@ @@ @@@@@ @@ @@
* @@@@@@ (((((((
* @@@@@#(((((((
* @@@@@(((((
* @@@((
*/
pragma solidity ^0.8.17.0;
interface IChamberGod {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event ChamberCreated(address indexed _chamber, address _owner, string _name, string _symbol);
event WizardAdded(address indexed _wizard);
event WizardRemoved(address indexed _wizard);
event AllowedContractAdded(address indexed _allowedContract);
event AllowedContractRemoved(address indexed _allowedContract);
/*//////////////////////////////////////////////////////////////
CHAMBER GOD LOGIC
//////////////////////////////////////////////////////////////*/
function createChamber(
string memory _name,
string memory _symbol,
address[] memory _constituents,
uint256[] memory _quantities,
address[] memory _wizards,
address[] memory _managers
) external returns (address);
function getWizards() external view returns (address[] memory);
function getChambers() external view returns (address[] memory);
function isWizard(address _wizard) external view returns (bool);
function isChamber(address _chamber) external view returns (bool);
function addWizard(address _wizard) external;
function removeWizard(address _wizard) external;
function getAllowedContracts() external view returns (address[] memory);
function addAllowedContract(address _target) external;
function removeAllowedContract(address _target) external;
function isAllowedContract(address _target) external view returns (bool);
}/**
* SPDX-License-Identifier: Apache License 2.0
*
* Copyright 2018 Set Labs Inc.
* Copyright 2022 Smash Works Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE
*
* This is a modified code from Set Labs Inc. found at
*
* https://github.com/SetProtocol/set-protocol-contracts
*
* All changes made by Smash Works Inc. are described and documented at
*
* https://docs.arch.finance/chambers
*
*
* %@@@@@
* @@@@@@@@@@@
* #@@@@@ @@@ @@ @@
* @@@@@@ @@@ @@@@ @@
* @@@@@@ @@ @@ @@ @@@@@ @@@@@ @@@*@@
* .@@@@@ @@@ @@@@@@@@ @@ @@ @@ @@
* @@@@@( ((((( @@@ @@@ @@ @@@@@ @@ @@
* @@@@@@ (((((((
* @@@@@#(((((((
* @@@@@(((((
* @@@((
*/
pragma solidity ^0.8.17.0;
import {IChamber} from "./IChamber.sol";
interface IIssuerWizard {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event ChamberTokenIssued(address indexed chamber, address indexed recipient, uint256 quantity);
event ChamberTokenRedeemed(
address indexed chamber, address indexed recipient, uint256 quantity
);
/*//////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////*/
function getConstituentsQuantitiesForIssuance(IChamber chamber, uint256 mintQuantity)
external
view
returns (address[] memory, uint256[] memory);
function getConstituentsQuantitiesForRedeem(IChamber chamber, uint256 redeemQuantity)
external
view
returns (address[] memory, uint256[] memory);
function issue(IChamber chamber, uint256 quantity) external;
function redeem(IChamber _chamber, uint256 _quantity) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "./ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
/// @notice Minimalist and modern Wrapped Ether implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)
/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)
contract WETH is ERC20("Wrapped Ether", "WETH", 18) {
using SafeTransferLib for address;
event Deposit(address indexed from, uint256 amount);
event Withdrawal(address indexed to, uint256 amount);
function deposit() public payable virtual {
_mint(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) public virtual {
_burn(msg.sender, amount);
emit Withdrawal(msg.sender, amount);
msg.sender.safeTransferETH(amount);
}
receive() external payable virtual {
deposit();
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() virtual {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}/**
* SPDX-License-Identifier: Apache License 2.0
*
* Copyright 2021 Index Cooperative
* Copyright 2023 Smash Works Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NOTICE
*
* This is a modified code from Index Cooperative found at
*
* https://github.com/IndexCoop/index-coop-smart-contracts
*
* All changes made by Smash Works Inc. are described and documented at
*
* https://docs.arch.finance/chambers
*
*
* %@@@@@
* @@@@@@@@@@@
* #@@@@@ @@@ @@ @@
* @@@@@@ @@@ @@@@ @@
* @@@@@@ @@ @@ @@ @@@@@ @@@@@ @@@*@@
* .@@@@@ @@@ @@@@@@@@ @@ @@ @@ @@
* @@@@@( ((((( @@@ @@@ @@ @@@@@ @@ @@
* @@@@@@ (((((((
* @@@@@#(((((((
* @@@@@(((((
* @@@((
*/
pragma solidity ^0.8.17.0;
import {IChamber} from "chambers/interfaces/IChamber.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IIssuerWizard} from "chambers/interfaces/IIssuerWizard.sol";
interface ITradeIssuerV2 {
/*//////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////*/
struct ContractCallInstruction {
address payable _target;
address _allowanceTarget;
IERC20 _sellToken;
uint256 _sellAmount;
IERC20 _buyToken;
uint256 _minBuyAmount;
bytes _callData;
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event AllowedTargetAdded(address indexed _target);
event AllowedTargetRemoved(address indexed _targer);
event TradeIssuerTokenMinted(
address indexed chamber,
address indexed recipient,
address indexed inputToken,
uint256 totalTokensUsed,
uint256 mintAmount
);
event TradeIssuerTokenRedeemed(
address indexed chamber,
address indexed recipient,
address indexed outputToken,
uint256 totalTokensReturned,
uint256 redeemAmount
);
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error CannotAllowTarget();
error CannotRemoveTarget();
error InvalidTarget(address target);
error LowLevelFunctionCallFailed();
error OversoldBaseToken();
error RedeemedForLessTokens();
error TargetAlreadyAllowed();
error UnderboughtAsset(IERC20 asset, uint256 buyAmount);
error UnderboughtConstituent(IERC20 asset, uint256 buyAmount);
error ZeroChamberAmount();
error ZeroBalanceAsset();
error ZeroNativeTokenSent();
error ZeroRequiredAmount();
/*//////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////*/
function getAllowedTargets() external returns (address[] memory);
function isAllowedTarget(address _target) external returns (bool);
function addTarget(address _target) external;
function removeTarget(address _target) external;
function transferERC20ToOwner(address _tokenToWithdraw) external;
function transferEthToOwner() external;
function mintChamberFromToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
IERC20 _baseToken,
uint256 _maxPayAmount,
uint256 _chamberAmount
) external returns (uint256 baseTokenUsed);
function mintChamberFromNativeToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
uint256 _chamberAmount
) external payable returns (uint256 wrappedNativeTokenUsed);
function redeemChamberToToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
IERC20 _baseToken,
uint256 _minReceiveAmount,
uint256 _chamberAmount
) external returns (uint256 baseTokenReturned);
function redeemChamberToNativeToken(
ContractCallInstruction[] memory _contractCallInstructions,
IChamber _chamber,
IIssuerWizard _issuerWizard,
uint256 _minReceiveAmount,
uint256 _chamberAmount
) external returns (uint256 wrappedNativeTokenReturned);
}{
"remappings": [
"@openzeppelin/=lib/openzeppelin-contracts/",
"chambers/=lib/chambers/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_wrappedNativeToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotAllowTarget","type":"error"},{"inputs":[],"name":"CannotRemoveTarget","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"InvalidTarget","type":"error"},{"inputs":[],"name":"LowLevelFunctionCallFailed","type":"error"},{"inputs":[],"name":"OversoldBaseToken","type":"error"},{"inputs":[],"name":"RedeemedForLessTokens","type":"error"},{"inputs":[],"name":"TargetAlreadyAllowed","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"buyAmount","type":"uint256"}],"name":"UnderboughtAsset","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"uint256","name":"buyAmount","type":"uint256"}],"name":"UnderboughtConstituent","type":"error"},{"inputs":[],"name":"ZeroBalanceAsset","type":"error"},{"inputs":[],"name":"ZeroChamberAmount","type":"error"},{"inputs":[],"name":"ZeroNativeTokenSent","type":"error"},{"inputs":[],"name":"ZeroRequiredAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_target","type":"address"}],"name":"AllowedTargetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_targer","type":"address"}],"name":"AllowedTargetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"chamber","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"inputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalTokensUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"TradeIssuerTokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"chamber","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalTokensReturned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"redeemAmount","type":"uint256"}],"name":"TradeIssuerTokenRedeemed","type":"event"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"addTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllowedTargets","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"isAllowedTarget","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"_target","type":"address"},{"internalType":"address","name":"_allowanceTarget","type":"address"},{"internalType":"contract IERC20","name":"_sellToken","type":"address"},{"internalType":"uint256","name":"_sellAmount","type":"uint256"},{"internalType":"contract IERC20","name":"_buyToken","type":"address"},{"internalType":"uint256","name":"_minBuyAmount","type":"uint256"},{"internalType":"bytes","name":"_callData","type":"bytes"}],"internalType":"struct ITradeIssuerV2.ContractCallInstruction[]","name":"_contractCallInstructions","type":"tuple[]"},{"internalType":"contract IChamber","name":"_chamber","type":"address"},{"internalType":"contract IIssuerWizard","name":"_issuerWizard","type":"address"},{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mintChamberFromNativeToken","outputs":[{"internalType":"uint256","name":"wrappedNativeTokenUsed","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"_target","type":"address"},{"internalType":"address","name":"_allowanceTarget","type":"address"},{"internalType":"contract IERC20","name":"_sellToken","type":"address"},{"internalType":"uint256","name":"_sellAmount","type":"uint256"},{"internalType":"contract IERC20","name":"_buyToken","type":"address"},{"internalType":"uint256","name":"_minBuyAmount","type":"uint256"},{"internalType":"bytes","name":"_callData","type":"bytes"}],"internalType":"struct ITradeIssuerV2.ContractCallInstruction[]","name":"_contractCallInstructions","type":"tuple[]"},{"internalType":"contract IChamber","name":"_chamber","type":"address"},{"internalType":"contract IIssuerWizard","name":"_issuerWizard","type":"address"},{"internalType":"contract IERC20","name":"_baseToken","type":"address"},{"internalType":"uint256","name":"_maxPayAmount","type":"uint256"},{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"mintChamberFromToken","outputs":[{"internalType":"uint256","name":"baseTokenUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"_target","type":"address"},{"internalType":"address","name":"_allowanceTarget","type":"address"},{"internalType":"contract IERC20","name":"_sellToken","type":"address"},{"internalType":"uint256","name":"_sellAmount","type":"uint256"},{"internalType":"contract IERC20","name":"_buyToken","type":"address"},{"internalType":"uint256","name":"_minBuyAmount","type":"uint256"},{"internalType":"bytes","name":"_callData","type":"bytes"}],"internalType":"struct ITradeIssuerV2.ContractCallInstruction[]","name":"_contractCallInstructions","type":"tuple[]"},{"internalType":"contract IChamber","name":"_chamber","type":"address"},{"internalType":"contract IIssuerWizard","name":"_issuerWizard","type":"address"},{"internalType":"uint256","name":"_minReceiveAmount","type":"uint256"},{"internalType":"uint256","name":"_redeemAmount","type":"uint256"}],"name":"redeemChamberToNativeToken","outputs":[{"internalType":"uint256","name":"wrappedNativeTokenReturned","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"_target","type":"address"},{"internalType":"address","name":"_allowanceTarget","type":"address"},{"internalType":"contract IERC20","name":"_sellToken","type":"address"},{"internalType":"uint256","name":"_sellAmount","type":"uint256"},{"internalType":"contract IERC20","name":"_buyToken","type":"address"},{"internalType":"uint256","name":"_minBuyAmount","type":"uint256"},{"internalType":"bytes","name":"_callData","type":"bytes"}],"internalType":"struct ITradeIssuerV2.ContractCallInstruction[]","name":"_contractCallInstructions","type":"tuple[]"},{"internalType":"contract IChamber","name":"_chamber","type":"address"},{"internalType":"contract IIssuerWizard","name":"_issuerWizard","type":"address"},{"internalType":"contract IERC20","name":"_baseToken","type":"address"},{"internalType":"uint256","name":"_minReceiveAmount","type":"uint256"},{"internalType":"uint256","name":"_redeemAmount","type":"uint256"}],"name":"redeemChamberToToken","outputs":[{"internalType":"uint256","name":"baseTokenReturned","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"removeTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenToWithdraw","type":"address"}],"name":"transferERC20ToOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferEthToOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a0604052600180553480156200001557600080fd5b5060405162002442380380620024428339810160408190526200003891620000a5565b620000433362000055565b6001600160a01b0316608052620000d7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b857600080fd5b81516001600160a01b0381168114620000d057600080fd5b9392505050565b60805161231e6200012460003960008181610132015281816107d001528181610848015281816108b60152818161095301528181610a1901528181610a790152610b02015261231e6000f3fe6080604052600436106100e15760003560e01c80638da5cb5b1161007f578063d4cbd6a711610059578063d4cbd6a714610264578063d5d7ff3c14610279578063e2c4abe814610299578063f2fde38b146102bb57600080fd5b80638da5cb5b14610213578063938320c014610231578063a3172fbb1461024457600080fd5b806354b6c7e4116100bb57806354b6c7e41461018c5780636de45dee146101ae578063715018a6146101ce57806378addb48146101e357600080fd5b80630eb60b5b146100ed57806317fcb39b146101205780634d7e6f451461016c57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611ea6565b6102db565b6040519081526020015b60405180910390f35b34801561012c57600080fd5b506101547f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610117565b34801561017857600080fd5b5061010d610187366004611ea6565b6103e1565b34801561019857600080fd5b506101ac6101a7366004611f2d565b610500565b005b3480156101ba57600080fd5b506101ac6101c9366004611f2d565b61064d565b3480156101da57600080fd5b506101ac61073b565b3480156101ef57600080fd5b506102036101fe366004611f2d565b61074f565b6040519015158152602001610117565b34801561021f57600080fd5b506000546001600160a01b0316610154565b61010d61023f366004611f4a565b610762565b34801561025057600080fd5b5061010d61025f366004611fb4565b6109b3565b34801561027057600080fd5b506101ac610b62565b34801561028557600080fd5b506101ac610294366004611f2d565b610bed565b3480156102a557600080fd5b506102ae610cb0565b6040516101179190612028565b3480156102c757600080fd5b506101ac6102d6366004611f2d565b610cc1565b60006001546001146103085760405162461bcd60e51b81526004016102ff90612075565b60405180910390fd5b6002600155600082900361032f57604051630fa07b4b60e01b815260040160405180910390fd5b6103446001600160a01b038716333085610d3a565b610351868587858b610dab565b90508281101561037457604051639f27f36b60e01b815260040160405180910390fd5b6103886001600160a01b0385163383610f06565b60408051828152602081018490526001600160a01b03808716923392918a16917fc69997f09f7df7360047259707fab3b1e2c79441a1a88043f0a7a5fcc93c0a91910160405180910390a4600180559695505050505050565b60006001546001146104055760405162461bcd60e51b81526004016102ff90612075565b6002600155600082900361042c57604051630fa07b4b60e01b815260040160405180910390fd5b6104416001600160a01b038516333086610d3a565b61044e868587858b610f3b565b9050808310156104705760405162d3fc8d60e21b815260040160405180910390fd5b600061047c82856120af565b90506104926001600160a01b0386163383610f06565b6104a66001600160a01b0388163385610f06565b60408051838152602081018590526001600160a01b03808816923392918b16917f31408477a87ae1c6ea1e79086e8a5067440ff31a3d0aa8d3ce66e50579f7862e910160405180910390a450600180559695505050505050565b610508611092565b60015460011461052a5760405162461bcd60e51b81526004016102ff90612075565b600260019081556040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610575573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059991906120c2565b10156105b85760405163f03c583960e01b815260040160405180910390fd5b6106466105cd6000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063591906120c2565b6001600160a01b0384169190610f06565b5060018055565b610655611092565b6001546001146106775760405162461bcd60e51b81526004016102ff90612075565b60026001556001600160a01b0381166106ae5760405163d08525e960e01b81526001600160a01b03821660048201526024016102ff565b6106b78161074f565b156106d8576040516001621e358160e31b0319815260040160405180910390fd5b6106e36002826110ec565b610700576040516309dad42d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f35d8c1289dcbbe1728d28b879d227889040f4378c13aa1120f4b7f2a855f7d7b90600090a25060018055565b610743611092565b61074d6000611108565b565b600061075c600283611158565b92915050565b60006001546001146107865760405162461bcd60e51b81526004016102ff90612075565b600260015560008290036107ad57604051630fa07b4b60e01b815260040160405180910390fd5b346000036107ce576040516303ccc6cf60e21b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561082957600080fd5b505af115801561083d573d6000803e3d6000fd5b505050505061086f847f0000000000000000000000000000000000000000000000000000000000000000858589610f3b565b9050803410156108915760405162d3fc8d60e21b815260040160405180910390fd5b600061089d82346120af565b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b50610927925033915083905061117a565b61093b6001600160a01b0386163385610f06565b60408051838152602081018590526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116923392918916917f31408477a87ae1c6ea1e79086e8a5067440ff31a3d0aa8d3ce66e50579f7862e910160405180910390a45060018055949350505050565b60006001546001146109d75760405162461bcd60e51b81526004016102ff90612075565b600260015560008290036109fe57604051630fa07b4b60e01b815260040160405180910390fd5b610a136001600160a01b038616333085610d3a565b610a40857f000000000000000000000000000000000000000000000000000000000000000086858a610dab565b905082811015610a6357604051639f27f36b60e01b815260040160405180910390fd5b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b50610aea925033915083905061117a565b60408051828152602081018490526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116923392918916917fc69997f09f7df7360047259707fab3b1e2c79441a1a88043f0a7a5fcc93c0a91910160405180910390a46001805595945050505050565b610b6a611092565b600154600114610b8c5760405162461bcd60e51b81526004016102ff90612075565b60026001908155471015610bb35760405163f03c583960e01b815260040160405180910390fd5b600080546040516001600160a01b03909116914780156108fc02929091818181858888f19350505050158015610646573d6000803e3d6000fd5b610bf5611092565b600154600114610c175760405162461bcd60e51b81526004016102ff90612075565b6002600155610c258161074f565b610c4d5760405163d08525e960e01b81526001600160a01b03821660048201526024016102ff565b610c58600282611293565b610c7557604051633134854360e01b815260040160405180910390fd5b6040516001600160a01b038216907fb72619c89e8f1eb50cd16d1f69177954c19183af3051059f471f712595a2340b90600090a25060018055565b6060610cbc60026112a8565b905090565b610cc9611092565b6001600160a01b038116610d2e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ff565b610d3781611108565b50565b6040516001600160a01b0380851660248301528316604482015260648101829052610da59085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526112b5565b50505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038716906370a0823190602401602060405180830381865afa158015610df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1891906120c2565b6040516301e9a69560e41b81526001600160a01b0389811660048301526024820187905291925090861690631e9a695090604401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b50505050610e8783611387565b6040516370a0823160e01b815230600482015281906001600160a01b038816906370a0823190602401602060405180830381865afa158015610ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef191906120c2565b610efb91906120af565b979650505050505050565b6040516001600160a01b038316602482015260448101829052610f3690849063a9059cbb60e01b90606401610d6e565b505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038716906370a0823190602401602060405180830381865afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa891906120c2565b9050610fb383611387565b610fbe87868661152b565b60405163219e412d60e21b81526001600160a01b0388811660048301526024820186905286169063867904b490604401600060405180830381600087803b15801561100857600080fd5b505af115801561101c573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b03891692506370a082319150602401602060405180830381865afa158015611064573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108891906120c2565b610efb90826120af565b6000546001600160a01b0316331461074d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ff565b6000611101836001600160a01b038416611713565b9392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526001830160205260408120541515611101565b804710156111ca5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016102ff565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611217576040519150601f19603f3d011682016040523d82523d6000602084013e61121c565b606091505b5050905080610f365760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016102ff565b6000611101836001600160a01b038416611762565b6060600061110183611855565b600061130a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166118b19092919063ffffffff16565b805190915015610f36578080602001905181019061132891906120db565b610f365760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102ff565b60005b81518110156115275760008282815181106113a7576113a76120fd565b602090810291909101015160808101516040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611402573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142691906120c2565b905061143f8260400151836020015184606001516118c8565b61145182600001518360c00151611988565b5060808201516040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156114a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c591906120c2565b6114cf91906120af565b9050808360a00151111561151157608083015160a0840151604051630e842e1f60e21b81526001600160a01b03909216600483015260248201526044016102ff565b505050808061151f90612113565b91505061138a565b5050565b604051633470361b60e21b81526001600160a01b03848116600483015260248201839052600091829185169063d1c0d86c90604401600060405180830381865afa15801561157d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115a59190810190612187565b9150915060005b825181101561170b578181815181106115c7576115c76120fd565b60200260200101518382815181106115e1576115e16120fd565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611631573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165591906120c2565b10156116bc5782818151811061166d5761166d6120fd565b6020026020010151828281518110611687576116876120fd565b602090810291909101015160405163d6c2c44560e01b81526001600160a01b03909216600483015260248201526044016102ff565b6116f98382815181106116d1576116d16120fd565b6020026020010151868484815181106116ec576116ec6120fd565b60200260200101516118c8565b8061170381612113565b9150506115ac565b505050505050565b600081815260018301602052604081205461175a5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561075c565b50600061075c565b6000818152600183016020526040812054801561184b5760006117866001836120af565b855490915060009061179a906001906120af565b90508181146117ff5760008660000182815481106117ba576117ba6120fd565b90600052602060002001549050808760000184815481106117dd576117dd6120fd565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118105761181061224c565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061075c565b600091505061075c565b6060816000018054806020026020016040519081016040528092919081815260200182805480156118a557602002820191906000526020600020905b815481526020019060010190808311611891575b50505050509050919050565b60606118c084846000856119f2565b949350505050565b806000036118e9576040516302dee0c960e31b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195d91906120c2565b905081811015610da557610da583611977836000196120af565b6001600160a01b0387169190611ac2565b60606119938361074f565b6119bb5760405163d08525e960e01b81526001600160a01b03841660048201526024016102ff565b6119ce6001600160a01b03841683611b74565b9050805160000361075c5760405163b9daf4ff60e01b815260040160405180910390fd5b606082471015611a535760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102ff565b600080866001600160a01b03168587604051611a6f9190612286565b60006040518083038185875af1925050503d8060008114611aac576040519150601f19603f3d011682016040523d82523d6000602084013e611ab1565b606091505b5091509150610efb87838387611bb8565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015611b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3791906120c2565b611b4191906122a2565b6040516001600160a01b038516602482015260448101829052909150610da590859063095ea7b360e01b90606401610d6e565b6060611101838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506119f2565b60608315611c27578251600003611c20576001600160a01b0385163b611c205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ff565b50816118c0565b6118c08383815115611c3c5781518083602001fd5b8060405162461bcd60e51b81526004016102ff91906122b5565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff81118282101715611c8f57611c8f611c56565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611cbe57611cbe611c56565b604052919050565b600067ffffffffffffffff821115611ce057611ce0611c56565b5060051b60200190565b6001600160a01b0381168114610d3757600080fd5b8035611d0a81611cea565b919050565b600082601f830112611d2057600080fd5b813567ffffffffffffffff811115611d3a57611d3a611c56565b611d4d601f8201601f1916602001611c95565b818152846020838601011115611d6257600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611d9057600080fd5b81356020611da5611da083611cc6565b611c95565b82815260059290921b84018101918181019086841115611dc457600080fd5b8286015b84811015611e9b57803567ffffffffffffffff80821115611de95760008081fd5b9088019060e0828b03601f1901811315611e035760008081fd5b611e0b611c6c565b611e16888501611cff565b81526040611e25818601611cff565b898301526060611e36818701611cff565b828401526080915081860135818401525060a0611e54818701611cff565b8284015260c0915081860135818401525082850135925083831115611e795760008081fd5b611e878d8a85880101611d0f565b908201528652505050918301918301611dc8565b509695505050505050565b60008060008060008060c08789031215611ebf57600080fd5b863567ffffffffffffffff811115611ed657600080fd5b611ee289828a01611d7f565b9650506020870135611ef381611cea565b94506040870135611f0381611cea565b93506060870135611f1381611cea565b9598949750929560808101359460a0909101359350915050565b600060208284031215611f3f57600080fd5b813561110181611cea565b60008060008060808587031215611f6057600080fd5b843567ffffffffffffffff811115611f7757600080fd5b611f8387828801611d7f565b9450506020850135611f9481611cea565b92506040850135611fa481611cea565b9396929550929360600135925050565b600080600080600060a08688031215611fcc57600080fd5b853567ffffffffffffffff811115611fe357600080fd5b611fef88828901611d7f565b955050602086013561200081611cea565b9350604086013561201081611cea565b94979396509394606081013594506080013592915050565b6020808252825182820181905260009190848201906040850190845b818110156120695783516001600160a01b031683529284019291840191600101612044565b50909695505050505050565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561075c5761075c612099565b6000602082840312156120d457600080fd5b5051919050565b6000602082840312156120ed57600080fd5b8151801515811461110157600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161212557612125612099565b5060010190565b600082601f83011261213d57600080fd5b8151602061214d611da083611cc6565b82815260059290921b8401810191818101908684111561216c57600080fd5b8286015b84811015611e9b5780518352918301918301612170565b6000806040838503121561219a57600080fd5b825167ffffffffffffffff808211156121b257600080fd5b818501915085601f8301126121c657600080fd5b815160206121d6611da083611cc6565b82815260059290921b840181019181810190898411156121f557600080fd5b948201945b8386101561221c57855161220d81611cea565b825294820194908201906121fa565b9188015191965090935050508082111561223557600080fd5b506122428582860161212c565b9150509250929050565b634e487b7160e01b600052603160045260246000fd5b60005b8381101561227d578181015183820152602001612265565b50506000910152565b60008251612298818460208701612262565b9190910192915050565b8082018082111561075c5761075c612099565b60208152600082518060208401526122d4816040850160208701612262565b601f01601f1916919091016040019291505056fea2646970667358221220f65b197f35e9989a2d9307438d82ccef17cba8d4cf0a3569af61edd32e2234a564736f6c63430008110033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x6080604052600436106100e15760003560e01c80638da5cb5b1161007f578063d4cbd6a711610059578063d4cbd6a714610264578063d5d7ff3c14610279578063e2c4abe814610299578063f2fde38b146102bb57600080fd5b80638da5cb5b14610213578063938320c014610231578063a3172fbb1461024457600080fd5b806354b6c7e4116100bb57806354b6c7e41461018c5780636de45dee146101ae578063715018a6146101ce57806378addb48146101e357600080fd5b80630eb60b5b146100ed57806317fcb39b146101205780634d7e6f451461016c57600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611ea6565b6102db565b6040519081526020015b60405180910390f35b34801561012c57600080fd5b506101547f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040516001600160a01b039091168152602001610117565b34801561017857600080fd5b5061010d610187366004611ea6565b6103e1565b34801561019857600080fd5b506101ac6101a7366004611f2d565b610500565b005b3480156101ba57600080fd5b506101ac6101c9366004611f2d565b61064d565b3480156101da57600080fd5b506101ac61073b565b3480156101ef57600080fd5b506102036101fe366004611f2d565b61074f565b6040519015158152602001610117565b34801561021f57600080fd5b506000546001600160a01b0316610154565b61010d61023f366004611f4a565b610762565b34801561025057600080fd5b5061010d61025f366004611fb4565b6109b3565b34801561027057600080fd5b506101ac610b62565b34801561028557600080fd5b506101ac610294366004611f2d565b610bed565b3480156102a557600080fd5b506102ae610cb0565b6040516101179190612028565b3480156102c757600080fd5b506101ac6102d6366004611f2d565b610cc1565b60006001546001146103085760405162461bcd60e51b81526004016102ff90612075565b60405180910390fd5b6002600155600082900361032f57604051630fa07b4b60e01b815260040160405180910390fd5b6103446001600160a01b038716333085610d3a565b610351868587858b610dab565b90508281101561037457604051639f27f36b60e01b815260040160405180910390fd5b6103886001600160a01b0385163383610f06565b60408051828152602081018490526001600160a01b03808716923392918a16917fc69997f09f7df7360047259707fab3b1e2c79441a1a88043f0a7a5fcc93c0a91910160405180910390a4600180559695505050505050565b60006001546001146104055760405162461bcd60e51b81526004016102ff90612075565b6002600155600082900361042c57604051630fa07b4b60e01b815260040160405180910390fd5b6104416001600160a01b038516333086610d3a565b61044e868587858b610f3b565b9050808310156104705760405162d3fc8d60e21b815260040160405180910390fd5b600061047c82856120af565b90506104926001600160a01b0386163383610f06565b6104a66001600160a01b0388163385610f06565b60408051838152602081018590526001600160a01b03808816923392918b16917f31408477a87ae1c6ea1e79086e8a5067440ff31a3d0aa8d3ce66e50579f7862e910160405180910390a450600180559695505050505050565b610508611092565b60015460011461052a5760405162461bcd60e51b81526004016102ff90612075565b600260019081556040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015610575573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059991906120c2565b10156105b85760405163f03c583960e01b815260040160405180910390fd5b6106466105cd6000546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063591906120c2565b6001600160a01b0384169190610f06565b5060018055565b610655611092565b6001546001146106775760405162461bcd60e51b81526004016102ff90612075565b60026001556001600160a01b0381166106ae5760405163d08525e960e01b81526001600160a01b03821660048201526024016102ff565b6106b78161074f565b156106d8576040516001621e358160e31b0319815260040160405180910390fd5b6106e36002826110ec565b610700576040516309dad42d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f35d8c1289dcbbe1728d28b879d227889040f4378c13aa1120f4b7f2a855f7d7b90600090a25060018055565b610743611092565b61074d6000611108565b565b600061075c600283611158565b92915050565b60006001546001146107865760405162461bcd60e51b81526004016102ff90612075565b600260015560008290036107ad57604051630fa07b4b60e01b815260040160405180910390fd5b346000036107ce576040516303ccc6cf60e21b815260040160405180910390fd5b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561082957600080fd5b505af115801561083d573d6000803e3d6000fd5b505050505061086f847f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2858589610f3b565b9050803410156108915760405162d3fc8d60e21b815260040160405180910390fd5b600061089d82346120af565b604051632e1a7d4d60e01b8152600481018290529091507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b50610927925033915083905061117a565b61093b6001600160a01b0386163385610f06565b60408051838152602081018590526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28116923392918916917f31408477a87ae1c6ea1e79086e8a5067440ff31a3d0aa8d3ce66e50579f7862e910160405180910390a45060018055949350505050565b60006001546001146109d75760405162461bcd60e51b81526004016102ff90612075565b600260015560008290036109fe57604051630fa07b4b60e01b815260040160405180910390fd5b610a136001600160a01b038616333085610d3a565b610a40857f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc286858a610dab565b905082811015610a6357604051639f27f36b60e01b815260040160405180910390fd5b604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b50610aea925033915083905061117a565b60408051828152602081018490526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28116923392918916917fc69997f09f7df7360047259707fab3b1e2c79441a1a88043f0a7a5fcc93c0a91910160405180910390a46001805595945050505050565b610b6a611092565b600154600114610b8c5760405162461bcd60e51b81526004016102ff90612075565b60026001908155471015610bb35760405163f03c583960e01b815260040160405180910390fd5b600080546040516001600160a01b03909116914780156108fc02929091818181858888f19350505050158015610646573d6000803e3d6000fd5b610bf5611092565b600154600114610c175760405162461bcd60e51b81526004016102ff90612075565b6002600155610c258161074f565b610c4d5760405163d08525e960e01b81526001600160a01b03821660048201526024016102ff565b610c58600282611293565b610c7557604051633134854360e01b815260040160405180910390fd5b6040516001600160a01b038216907fb72619c89e8f1eb50cd16d1f69177954c19183af3051059f471f712595a2340b90600090a25060018055565b6060610cbc60026112a8565b905090565b610cc9611092565b6001600160a01b038116610d2e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016102ff565b610d3781611108565b50565b6040516001600160a01b0380851660248301528316604482015260648101829052610da59085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526112b5565b50505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038716906370a0823190602401602060405180830381865afa158015610df4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1891906120c2565b6040516301e9a69560e41b81526001600160a01b0389811660048301526024820187905291925090861690631e9a695090604401600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b50505050610e8783611387565b6040516370a0823160e01b815230600482015281906001600160a01b038816906370a0823190602401602060405180830381865afa158015610ecd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef191906120c2565b610efb91906120af565b979650505050505050565b6040516001600160a01b038316602482015260448101829052610f3690849063a9059cbb60e01b90606401610d6e565b505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038716906370a0823190602401602060405180830381865afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa891906120c2565b9050610fb383611387565b610fbe87868661152b565b60405163219e412d60e21b81526001600160a01b0388811660048301526024820186905286169063867904b490604401600060405180830381600087803b15801561100857600080fd5b505af115801561101c573d6000803e3d6000fd5b50506040516370a0823160e01b81523060048201526001600160a01b03891692506370a082319150602401602060405180830381865afa158015611064573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108891906120c2565b610efb90826120af565b6000546001600160a01b0316331461074d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ff565b6000611101836001600160a01b038416611713565b9392505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526001830160205260408120541515611101565b804710156111ca5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016102ff565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611217576040519150601f19603f3d011682016040523d82523d6000602084013e61121c565b606091505b5050905080610f365760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016102ff565b6000611101836001600160a01b038416611762565b6060600061110183611855565b600061130a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166118b19092919063ffffffff16565b805190915015610f36578080602001905181019061132891906120db565b610f365760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102ff565b60005b81518110156115275760008282815181106113a7576113a76120fd565b602090810291909101015160808101516040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611402573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142691906120c2565b905061143f8260400151836020015184606001516118c8565b61145182600001518360c00151611988565b5060808201516040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156114a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c591906120c2565b6114cf91906120af565b9050808360a00151111561151157608083015160a0840151604051630e842e1f60e21b81526001600160a01b03909216600483015260248201526044016102ff565b505050808061151f90612113565b91505061138a565b5050565b604051633470361b60e21b81526001600160a01b03848116600483015260248201839052600091829185169063d1c0d86c90604401600060405180830381865afa15801561157d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115a59190810190612187565b9150915060005b825181101561170b578181815181106115c7576115c76120fd565b60200260200101518382815181106115e1576115e16120fd565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611631573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165591906120c2565b10156116bc5782818151811061166d5761166d6120fd565b6020026020010151828281518110611687576116876120fd565b602090810291909101015160405163d6c2c44560e01b81526001600160a01b03909216600483015260248201526044016102ff565b6116f98382815181106116d1576116d16120fd565b6020026020010151868484815181106116ec576116ec6120fd565b60200260200101516118c8565b8061170381612113565b9150506115ac565b505050505050565b600081815260018301602052604081205461175a5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561075c565b50600061075c565b6000818152600183016020526040812054801561184b5760006117866001836120af565b855490915060009061179a906001906120af565b90508181146117ff5760008660000182815481106117ba576117ba6120fd565b90600052602060002001549050808760000184815481106117dd576117dd6120fd565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806118105761181061224c565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061075c565b600091505061075c565b6060816000018054806020026020016040519081016040528092919081815260200182805480156118a557602002820191906000526020600020905b815481526020019060010190808311611891575b50505050509050919050565b60606118c084846000856119f2565b949350505050565b806000036118e9576040516302dee0c960e31b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061195d91906120c2565b905081811015610da557610da583611977836000196120af565b6001600160a01b0387169190611ac2565b60606119938361074f565b6119bb5760405163d08525e960e01b81526001600160a01b03841660048201526024016102ff565b6119ce6001600160a01b03841683611b74565b9050805160000361075c5760405163b9daf4ff60e01b815260040160405180910390fd5b606082471015611a535760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102ff565b600080866001600160a01b03168587604051611a6f9190612286565b60006040518083038185875af1925050503d8060008114611aac576040519150601f19603f3d011682016040523d82523d6000602084013e611ab1565b606091505b5091509150610efb87838387611bb8565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015611b13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3791906120c2565b611b4191906122a2565b6040516001600160a01b038516602482015260448101829052909150610da590859063095ea7b360e01b90606401610d6e565b6060611101838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506119f2565b60608315611c27578251600003611c20576001600160a01b0385163b611c205760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102ff565b50816118c0565b6118c08383815115611c3c5781518083602001fd5b8060405162461bcd60e51b81526004016102ff91906122b5565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff81118282101715611c8f57611c8f611c56565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611cbe57611cbe611c56565b604052919050565b600067ffffffffffffffff821115611ce057611ce0611c56565b5060051b60200190565b6001600160a01b0381168114610d3757600080fd5b8035611d0a81611cea565b919050565b600082601f830112611d2057600080fd5b813567ffffffffffffffff811115611d3a57611d3a611c56565b611d4d601f8201601f1916602001611c95565b818152846020838601011115611d6257600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112611d9057600080fd5b81356020611da5611da083611cc6565b611c95565b82815260059290921b84018101918181019086841115611dc457600080fd5b8286015b84811015611e9b57803567ffffffffffffffff80821115611de95760008081fd5b9088019060e0828b03601f1901811315611e035760008081fd5b611e0b611c6c565b611e16888501611cff565b81526040611e25818601611cff565b898301526060611e36818701611cff565b828401526080915081860135818401525060a0611e54818701611cff565b8284015260c0915081860135818401525082850135925083831115611e795760008081fd5b611e878d8a85880101611d0f565b908201528652505050918301918301611dc8565b509695505050505050565b60008060008060008060c08789031215611ebf57600080fd5b863567ffffffffffffffff811115611ed657600080fd5b611ee289828a01611d7f565b9650506020870135611ef381611cea565b94506040870135611f0381611cea565b93506060870135611f1381611cea565b9598949750929560808101359460a0909101359350915050565b600060208284031215611f3f57600080fd5b813561110181611cea565b60008060008060808587031215611f6057600080fd5b843567ffffffffffffffff811115611f7757600080fd5b611f8387828801611d7f565b9450506020850135611f9481611cea565b92506040850135611fa481611cea565b9396929550929360600135925050565b600080600080600060a08688031215611fcc57600080fd5b853567ffffffffffffffff811115611fe357600080fd5b611fef88828901611d7f565b955050602086013561200081611cea565b9350604086013561201081611cea565b94979396509394606081013594506080013592915050565b6020808252825182820181905260009190848201906040850190845b818110156120695783516001600160a01b031683529284019291840191600101612044565b50909695505050505050565b6020808252600a90820152695245454e5452414e435960b01b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561075c5761075c612099565b6000602082840312156120d457600080fd5b5051919050565b6000602082840312156120ed57600080fd5b8151801515811461110157600080fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161212557612125612099565b5060010190565b600082601f83011261213d57600080fd5b8151602061214d611da083611cc6565b82815260059290921b8401810191818101908684111561216c57600080fd5b8286015b84811015611e9b5780518352918301918301612170565b6000806040838503121561219a57600080fd5b825167ffffffffffffffff808211156121b257600080fd5b818501915085601f8301126121c657600080fd5b815160206121d6611da083611cc6565b82815260059290921b840181019181810190898411156121f557600080fd5b948201945b8386101561221c57855161220d81611cea565b825294820194908201906121fa565b9188015191965090935050508082111561223557600080fd5b506122428582860161212c565b9150509250929050565b634e487b7160e01b600052603160045260246000fd5b60005b8381101561227d578181015183820152602001612265565b50506000910152565b60008251612298818460208701612262565b9190910192915050565b8082018082111561075c5761075c612099565b60208152600082518060208401526122d4816040850160208701612262565b601f01601f1916919091016040019291505056fea2646970667358221220f65b197f35e9989a2d9307438d82ccef17cba8d4cf0a3569af61edd32e2234a564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
-----Decoded View---------------
Arg [0] : _wrappedNativeToken (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.62
Net Worth in ETH
0.000315
Token Allocations
SFRXETH
42.59%
YVWETH
28.73%
MONKY
28.68%
Multichain Portfolio | 33 Chains
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.