Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TokensFactory
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "./utils/ShareCollateralToken.sol"; import "./utils/ShareDebtToken.sol"; import "./interfaces/ITokensFactory.sol"; /// @title TokensFactory /// @notice Deploys debt and collateral tokens for each Silo /// @custom:security-contact [email protected] contract TokensFactory is ITokensFactory { ISiloRepository public siloRepository; event InitSiloRepository(); error OnlySilo(); error SiloRepositoryAlreadySet(); modifier onlySilo() { if (!siloRepository.isSilo(msg.sender)) revert OnlySilo(); _; } /// @inheritdoc ITokensFactory function initRepository(address _repository) external { // We don't perform a ping to the repository because this is meant to be called in its constructor if (address(siloRepository) != address(0)) revert SiloRepositoryAlreadySet(); siloRepository = ISiloRepository(_repository); emit InitSiloRepository(); } /// @inheritdoc ITokensFactory function createShareCollateralToken( string memory _name, string memory _symbol, address _asset ) external override onlySilo returns (IShareToken token) { token = new ShareCollateralToken(_name, _symbol, msg.sender, _asset); emit NewShareCollateralTokenCreated(address(token)); } /// @inheritdoc ITokensFactory function createShareDebtToken( string memory _name, string memory _symbol, address _asset ) external override onlySilo returns (IShareToken token) { token = new ShareDebtToken(_name, _symbol, msg.sender, _asset); emit NewShareDebtTokenCreated(address(token)); } function tokensFactoryPing() external pure override returns (bytes4) { return this.tokensFactoryPing.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// 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: BUSL-1.1 pragma solidity 0.8.13; import "./IShareToken.sol"; import "./IFlashLiquidationReceiver.sol"; import "./ISiloRepository.sol"; interface IBaseSilo { enum AssetStatus { Undefined, Active, Removed } /// @dev Storage struct that holds all required data for a single token market struct AssetStorage { /// @dev Token that represents a share in totalDeposits of Silo IShareToken collateralToken; /// @dev Token that represents a share in collateralOnlyDeposits of Silo IShareToken collateralOnlyToken; /// @dev Token that represents a share in totalBorrowAmount of Silo IShareToken debtToken; /// @dev COLLATERAL: Amount of asset token that has been deposited to Silo with interest earned by depositors. /// It also includes token amount that has been borrowed. uint256 totalDeposits; /// @dev COLLATERAL ONLY: Amount of asset token that has been deposited to Silo that can be ONLY used /// as collateral. These deposits do NOT earn interest and CANNOT be borrowed. uint256 collateralOnlyDeposits; /// @dev DEBT: Amount of asset token that has been borrowed with accrued interest. uint256 totalBorrowAmount; } /// @dev Storage struct that holds data related to fees and interest struct AssetInterestData { /// @dev Total amount of already harvested protocol fees uint256 harvestedProtocolFees; /// @dev Total amount (ever growing) of asset token that has been earned by the protocol from /// generated interest. uint256 protocolFees; /// @dev Timestamp of the last time `interestRate` has been updated in storage. uint64 interestRateTimestamp; /// @dev True if asset was removed from the protocol. If so, deposit and borrow functions are disabled /// for that asset AssetStatus status; } /// @notice data that InterestModel needs for calculations struct UtilizationData { uint256 totalDeposits; uint256 totalBorrowAmount; /// @dev timestamp of last interest accrual uint64 interestRateTimestamp; } /// @dev Shares names and symbols that are generated while asset initialization struct AssetSharesMetadata { /// @dev Name for the collateral shares token string collateralName; /// @dev Symbol for the collateral shares token string collateralSymbol; /// @dev Name for the collateral only (protected collateral) shares token string protectedName; /// @dev Symbol for the collateral only (protected collateral) shares token string protectedSymbol; /// @dev Name for the debt shares token string debtName; /// @dev Symbol for the debt shares token string debtSymbol; } /// @notice Emitted when deposit is made /// @param asset asset address that was deposited /// @param depositor wallet address that deposited asset /// @param amount amount of asset that was deposited /// @param collateralOnly type of deposit, true if collateralOnly deposit was used event Deposit(address indexed asset, address indexed depositor, uint256 amount, bool collateralOnly); /// @notice Emitted when withdraw is made /// @param asset asset address that was withdrawn /// @param depositor wallet address that deposited asset /// @param receiver wallet address that received asset /// @param amount amount of asset that was withdrew /// @param collateralOnly type of withdraw, true if collateralOnly deposit was used event Withdraw( address indexed asset, address indexed depositor, address indexed receiver, uint256 amount, bool collateralOnly ); /// @notice Emitted on asset borrow /// @param asset asset address that was borrowed /// @param user wallet address that borrowed asset /// @param amount amount of asset that was borrowed event Borrow(address indexed asset, address indexed user, uint256 amount); /// @notice Emitted on asset repay /// @param asset asset address that was repaid /// @param user wallet address that repaid asset /// @param amount amount of asset that was repaid event Repay(address indexed asset, address indexed user, uint256 amount); /// @notice Emitted on user liquidation /// @param asset asset address that was liquidated /// @param user wallet address that was liquidated /// @param shareAmountRepaid amount of collateral-share token that was repaid. This is collateral token representing /// ownership of underlying deposit. /// @param seizedCollateral amount of underlying token that was seized by liquidator event Liquidate(address indexed asset, address indexed user, uint256 shareAmountRepaid, uint256 seizedCollateral); /// @notice Emitted when the status for an asset is updated /// @param asset asset address that was updated /// @param status new asset status event AssetStatusUpdate(address indexed asset, AssetStatus indexed status); /// @return version of the silo contract function VERSION() external returns (uint128); // solhint-disable-line func-name-mixedcase /// @notice Synchronize current bridge assets with Silo /// @dev This function needs to be called on Silo deployment to setup all assets for Silo. It needs to be /// called every time a bridged asset is added or removed. When bridge asset is removed, depositing and borrowing /// should be disabled during asset sync. function syncBridgeAssets() external; /// @notice Get Silo Repository contract address /// @return Silo Repository contract address function siloRepository() external view returns (ISiloRepository); /// @notice Get asset storage data /// @param _asset asset address /// @return AssetStorage struct function assetStorage(address _asset) external view returns (AssetStorage memory); /// @notice Get asset interest data /// @param _asset asset address /// @return AssetInterestData struct function interestData(address _asset) external view returns (AssetInterestData memory); /// @dev helper method for InterestRateModel calculations function utilizationData(address _asset) external view returns (UtilizationData memory data); /// @notice Calculates solvency of an account /// @param _user wallet address for which solvency is calculated /// @return true if solvent, false otherwise function isSolvent(address _user) external view returns (bool); /// @notice Returns all initialized (synced) assets of Silo including current and removed bridge assets /// @return assets array of initialized assets of Silo function getAssets() external view returns (address[] memory assets); /// @notice Returns all initialized (synced) assets of Silo including current and removed bridge assets /// with corresponding state /// @return assets array of initialized assets of Silo /// @return assetsStorage array of assets state corresponding to `assets` array function getAssetsWithState() external view returns (address[] memory assets, AssetStorage[] memory assetsStorage); /// @notice Check if depositing an asset for given account is possible /// @dev Depositing an asset that has been already borrowed (and vice versa) is disallowed /// @param _asset asset we want to deposit /// @param _depositor depositor address /// @return true if asset can be deposited by depositor function depositPossible(address _asset, address _depositor) external view returns (bool); /// @notice Check if borrowing an asset for given account is possible /// @dev Borrowing an asset that has been already deposited (and vice versa) is disallowed /// @param _asset asset we want to deposit /// @param _borrower borrower address /// @return true if asset can be borrowed by borrower function borrowPossible(address _asset, address _borrower) external view returns (bool); /// @dev Amount of token that is available for borrowing /// @param _asset asset to get liquidity for /// @return Silo liquidity function liquidity(address _asset) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @dev This interface stands for "ERC20 Reversed", /// in the sense that the recipient of a transfer needs to approve the transfer amount first interface IERC20R is IERC20 { /// @dev Emitted when the allowance of a `_receiver` for an `_owner` is set by /// a call to {changeReceiveApproval}. `value` is the new allowance. /// @param _owner previous owner of the debt /// @param _receiver wallet that received debt /// @param _value amount of token transferred event ReceiveApproval(address indexed _owner, address indexed _receiver, uint256 _value); /// @dev Atomically decreases the receive allowance granted to `owner` by the caller. /// This is an alternative to {receive approve} that can be used as a mitigation for problems /// described in {IERC20-approve}. /// Emits an {ReceiveApproval} event indicating the updated receive allowance. /// @param _owner owner of debt token that is being allowed sending it to the caller /// @param _subtractedValue amount of token to decrease allowance function decreaseReceiveAllowance(address _owner, uint256 _subtractedValue) external; /// @dev Atomically increases the receive allowance granted to `owner` by the caller. /// This is an alternative to {receive approve} that can be used as a mitigation for problems /// described in {IERC20-approve}. /// Emits an {ReceiveApproval} event indicating the updated receive allowance. /// @param _owner owner of debt token that is being allowed sending it to the caller /// @param _addedValue amount of token to increase allowance function increaseReceiveAllowance(address _owner, uint256 _addedValue) external; /// @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 /// OR use increase/decrease approval method instead. /// Emits an {ReceiveApproval} event. /// @param _owner owner of debt token that is being allowed sending it to the caller /// @param _amount amount of token allowance function setReceiveApproval(address _owner, uint256 _amount) external; /// @dev Returns the remaining number of tokens that `_owner` is allowed to send to `_receiver` /// through {transferFrom}. This is zero by default. /// @param _owner owner of debt token /// @param _receiver wallet that is receiving debt tokens /// @return current token allowance function receiveAllowance(address _owner, address _receiver) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @dev when performing Silo flash liquidation, FlashReceiver contract will receive all collaterals interface IFlashLiquidationReceiver { /// @dev this method is called when doing Silo flash liquidation /// one can NOT assume, that if _seizedCollateral[i] != 0, then _shareAmountsToRepaid[i] must be 0 /// one should assume, that any combination of amounts is possible /// on callback, one must call `Silo.repayFor` because at the end of transaction, /// Silo will check if borrower is solvent. /// @param _user user address, that is liquidated /// @param _assets array of collateral assets received during user liquidation /// this array contains all assets (collateral borrowed) without any order /// @param _receivedCollaterals array of collateral amounts received during user liquidation /// indexes of amounts are related to `_assets`, /// @param _shareAmountsToRepaid array of amounts to repay for each asset /// indexes of amounts are related to `_assets`, /// @param _flashReceiverData data that are passed from sender that executes liquidation function siloLiquidationCallback( address _user, address[] calldata _assets, uint256[] calldata _receivedCollaterals, uint256[] calldata _shareAmountsToRepaid, bytes memory _flashReceiverData ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; interface IInterestRateModel { /* solhint-disable */ struct Config { // uopt ∈ (0, 1) – optimal utilization; int256 uopt; // ucrit ∈ (uopt, 1) – threshold of large utilization; int256 ucrit; // ulow ∈ (0, uopt) – threshold of low utilization int256 ulow; // ki > 0 – integrator gain int256 ki; // kcrit > 0 – proportional gain for large utilization int256 kcrit; // klow ≥ 0 – proportional gain for low utilization int256 klow; // klin ≥ 0 – coefficient of the lower linear bound int256 klin; // beta ≥ 0 - a scaling factor int256 beta; // ri ≥ 0 – initial value of the integrator int256 ri; // Tcrit ≥ 0 - the time during which the utilization exceeds the critical value int256 Tcrit; } /* solhint-enable */ /// @dev Set dedicated config for given asset in a Silo. Config is per asset per Silo so different assets /// in different Silo can have different configs. /// It will try to call `_silo.accrueInterest(_asset)` before updating config, but it is not guaranteed, /// that this call will be successful, if it fail config will be set anyway. /// @param _silo Silo address for which config should be set /// @param _asset asset address for which config should be set function setConfig(address _silo, address _asset, Config calldata _config) external; /// @dev get compound interest rate and update model storage /// @param _asset address of an asset in Silo for which interest rate should be calculated /// @param _blockTimestamp current block timestamp /// @return rcomp compounded interest rate from last update until now (1e18 == 100%) function getCompoundInterestRateAndUpdate( address _asset, uint256 _blockTimestamp ) external returns (uint256 rcomp); /// @dev Get config for given asset in a Silo. If dedicated config is not set, default one will be returned. /// @param _silo Silo address for which config should be set /// @param _asset asset address for which config should be set /// @return Config struct for asset in Silo function getConfig(address _silo, address _asset) external view returns (Config memory); /// @dev get compound interest rate /// @param _silo address of Silo /// @param _asset address of an asset in Silo for which interest rate should be calculated /// @param _blockTimestamp current block timestamp /// @return rcomp compounded interest rate from last update until now (1e18 == 100%) function getCompoundInterestRate( address _silo, address _asset, uint256 _blockTimestamp ) external view returns (uint256 rcomp); /// @dev get current annual interest rate /// @param _silo address of Silo /// @param _asset address of an asset in Silo for which interest rate should be calculated /// @param _blockTimestamp current block timestamp /// @return rcur current annual interest rate (1e18 == 100%) function getCurrentInterestRate( address _silo, address _asset, uint256 _blockTimestamp ) external view returns (uint256 rcur); /// @notice get the flag to detect rcomp restriction (zero current interest) due to overflow /// overflow boolean flag to detect rcomp restriction function overflowDetected( address _silo, address _asset, uint256 _blockTimestamp ) external view returns (bool overflow); /// @dev pure function that calculates current annual interest rate /// @param _c configuration object, InterestRateModel.Config /// @param _totalBorrowAmount current total borrows for asset /// @param _totalDeposits current total deposits for asset /// @param _interestRateTimestamp timestamp of last interest rate update /// @param _blockTimestamp current block timestamp /// @return rcur current annual interest rate (1e18 == 100%) function calculateCurrentInterestRate( Config memory _c, uint256 _totalDeposits, uint256 _totalBorrowAmount, uint256 _interestRateTimestamp, uint256 _blockTimestamp ) external pure returns (uint256 rcur); /// @dev pure function that calculates interest rate based on raw input data /// @param _c configuration object, InterestRateModel.Config /// @param _totalBorrowAmount current total borrows for asset /// @param _totalDeposits current total deposits for asset /// @param _interestRateTimestamp timestamp of last interest rate update /// @param _blockTimestamp current block timestamp /// @return rcomp compounded interest rate from last update until now (1e18 == 100%) /// @return ri current integral part of the rate /// @return Tcrit time during which the utilization exceeds the critical value /// @return overflow boolean flag to detect rcomp restriction function calculateCompoundInterestRateWithOverflowDetection( Config memory _c, uint256 _totalDeposits, uint256 _totalBorrowAmount, uint256 _interestRateTimestamp, uint256 _blockTimestamp ) external pure returns ( uint256 rcomp, int256 ri, int256 Tcrit, // solhint-disable-line var-name-mixedcase bool overflow ); /// @dev pure function that calculates interest rate based on raw input data /// @param _c configuration object, InterestRateModel.Config /// @param _totalBorrowAmount current total borrows for asset /// @param _totalDeposits current total deposits for asset /// @param _interestRateTimestamp timestamp of last interest rate update /// @param _blockTimestamp current block timestamp /// @return rcomp compounded interest rate from last update until now (1e18 == 100%) /// @return ri current integral part of the rate /// @return Tcrit time during which the utilization exceeds the critical value function calculateCompoundInterestRate( Config memory _c, uint256 _totalDeposits, uint256 _totalBorrowAmount, uint256 _interestRateTimestamp, uint256 _blockTimestamp ) external pure returns ( uint256 rcomp, int256 ri, int256 Tcrit // solhint-disable-line var-name-mixedcase ); /// @dev returns decimal points used by model function DP() external pure returns (uint256); // solhint-disable-line func-name-mixedcase /// @dev just a helper method to see if address is a InterestRateModel /// @return always true function interestRateModelPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; /// @title Common interface for Silo Incentive Contract interface INotificationReceiver { /// @dev Informs the contract about token transfer /// @param _token address of the token that was transferred /// @param _from sender /// @param _to receiver /// @param _amount amount that was transferred function onAfterTransfer(address _token, address _from, address _to, uint256 _amount) external; /// @dev Sanity check function /// @return always true function notificationReceiverPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.7.6 <0.9.0; /// @title Common interface for Silo Price Providers interface IPriceProvider { /// @notice Returns "Time-Weighted Average Price" for an asset. Calculates TWAP price for quote/asset. /// It unifies all tokens decimal to 18, examples: /// - if asses == quote it returns 1e18 /// - if asset is USDC and quote is ETH and ETH costs ~$3300 then it returns ~0.0003e18 WETH per 1 USDC /// @param _asset address of an asset for which to read price /// @return price of asses with 18 decimals, throws when pool is not ready yet to provide price function getPrice(address _asset) external view returns (uint256 price); /// @dev Informs if PriceProvider is setup for asset. It does not means PriceProvider can provide price right away. /// Some providers implementations need time to "build" buffer for TWAP price, /// so price may not be available yet but this method will return true. /// @param _asset asset in question /// @return TRUE if asset has been setup, otherwise false function assetSupported(address _asset) external view returns (bool); /// @notice Gets token address in which prices are quoted /// @return quoteToken address function quoteToken() external view returns (address); /// @notice Helper method that allows easily detects, if contract is PriceProvider /// @dev this can save us from simple human errors, in case we use invalid address /// but this should NOT be treated as security check /// @return always true function priceProviderPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.7.6 <0.9.0; import "./IPriceProvider.sol"; interface IPriceProvidersRepository { /// @notice Emitted when price provider is added /// @param newPriceProvider new price provider address event NewPriceProvider(IPriceProvider indexed newPriceProvider); /// @notice Emitted when price provider is removed /// @param priceProvider removed price provider address event PriceProviderRemoved(IPriceProvider indexed priceProvider); /// @notice Emitted when asset is assigned to price provider /// @param asset assigned asset address /// @param priceProvider price provider address event PriceProviderForAsset(address indexed asset, IPriceProvider indexed priceProvider); /// @notice Register new price provider /// @param _priceProvider address of price provider function addPriceProvider(IPriceProvider _priceProvider) external; /// @notice Unregister price provider /// @param _priceProvider address of price provider to be removed function removePriceProvider(IPriceProvider _priceProvider) external; /// @notice Sets price provider for asset /// @dev Request for asset price is forwarded to the price provider assigned to that asset /// @param _asset address of an asset for which price provider will be used /// @param _priceProvider address of price provider function setPriceProviderForAsset(address _asset, IPriceProvider _priceProvider) external; /// @notice Returns "Time-Weighted Average Price" for an asset /// @param _asset address of an asset for which to read price /// @return price TWAP price of a token with 18 decimals function getPrice(address _asset) external view returns (uint256 price); /// @notice Gets price provider assigned to an asset /// @param _asset address of an asset for which to get price provider /// @return priceProvider address of price provider function priceProviders(address _asset) external view returns (IPriceProvider priceProvider); /// @notice Gets token address in which prices are quoted /// @return quoteToken address function quoteToken() external view returns (address); /// @notice Gets manager role address /// @return manager role address function manager() external view returns (address); /// @notice Checks if providers are available for an asset /// @param _asset asset address to check /// @return returns TRUE if price feed is ready, otherwise false function providersReadyForAsset(address _asset) external view returns (bool); /// @notice Returns true if address is a registered price provider /// @param _provider address of price provider to be removed /// @return true if address is a registered price provider, otherwise false function isPriceProvider(IPriceProvider _provider) external view returns (bool); /// @notice Gets number of price providers registered /// @return number of price providers registered function providersCount() external view returns (uint256); /// @notice Gets an array of price providers /// @return array of price providers function providerList() external view returns (address[] memory); /// @notice Sanity check function /// @return returns always TRUE function priceProvidersRepositoryPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "./INotificationReceiver.sol"; interface IShareToken is IERC20Metadata { /// @notice Emitted every time receiver is notified about token transfer /// @param notificationReceiver receiver address /// @param success false if TX reverted on `notificationReceiver` side, otherwise true event NotificationSent( INotificationReceiver indexed notificationReceiver, bool success ); /// @notice Mint method for Silo to create debt position /// @param _account wallet for which to mint token /// @param _amount amount of token to be minted function mint(address _account, uint256 _amount) external; /// @notice Burn method for Silo to close debt position /// @param _account wallet for which to burn token /// @param _amount amount of token to be burned function burn(address _account, uint256 _amount) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "./IBaseSilo.sol"; interface ISilo is IBaseSilo { /// @notice Deposit `_amount` of `_asset` tokens from `msg.sender` to the Silo /// @param _asset The address of the token to deposit /// @param _amount The amount of the token to deposit /// @param _collateralOnly True if depositing collateral only /// @return collateralAmount deposited amount /// @return collateralShare user collateral shares based on deposited amount function deposit(address _asset, uint256 _amount, bool _collateralOnly) external returns (uint256 collateralAmount, uint256 collateralShare); /// @notice Router function to deposit `_amount` of `_asset` tokens to the Silo for the `_depositor` /// @param _asset The address of the token to deposit /// @param _depositor The address of the recipient of collateral tokens /// @param _amount The amount of the token to deposit /// @param _collateralOnly True if depositing collateral only /// @return collateralAmount deposited amount /// @return collateralShare `_depositor` collateral shares based on deposited amount function depositFor(address _asset, address _depositor, uint256 _amount, bool _collateralOnly) external returns (uint256 collateralAmount, uint256 collateralShare); /// @notice Withdraw `_amount` of `_asset` tokens from the Silo to `msg.sender` /// @param _asset The address of the token to withdraw /// @param _amount The amount of the token to withdraw /// @param _collateralOnly True if withdrawing collateral only deposit /// @return withdrawnAmount withdrawn amount that was transferred to user /// @return withdrawnShare burned share based on `withdrawnAmount` function withdraw(address _asset, uint256 _amount, bool _collateralOnly) external returns (uint256 withdrawnAmount, uint256 withdrawnShare); /// @notice Router function to withdraw `_amount` of `_asset` tokens from the Silo for the `_depositor` /// @param _asset The address of the token to withdraw /// @param _depositor The address that originally deposited the collateral tokens being withdrawn, /// it should be the one initiating the withdrawal through the router /// @param _receiver The address that will receive the withdrawn tokens /// @param _amount The amount of the token to withdraw /// @param _collateralOnly True if withdrawing collateral only deposit /// @return withdrawnAmount withdrawn amount that was transferred to `_receiver` /// @return withdrawnShare burned share based on `withdrawnAmount` function withdrawFor( address _asset, address _depositor, address _receiver, uint256 _amount, bool _collateralOnly ) external returns (uint256 withdrawnAmount, uint256 withdrawnShare); /// @notice Borrow `_amount` of `_asset` tokens from the Silo to `msg.sender` /// @param _asset The address of the token to borrow /// @param _amount The amount of the token to borrow /// @return debtAmount borrowed amount /// @return debtShare user debt share based on borrowed amount function borrow(address _asset, uint256 _amount) external returns (uint256 debtAmount, uint256 debtShare); /// @notice Router function to borrow `_amount` of `_asset` tokens from the Silo for the `_receiver` /// @param _asset The address of the token to borrow /// @param _borrower The address that will take the loan, /// it should be the one initiating the borrowing through the router /// @param _receiver The address of the asset receiver /// @param _amount The amount of the token to borrow /// @return debtAmount borrowed amount /// @return debtShare `_receiver` debt share based on borrowed amount function borrowFor(address _asset, address _borrower, address _receiver, uint256 _amount) external returns (uint256 debtAmount, uint256 debtShare); /// @notice Repay `_amount` of `_asset` tokens from `msg.sender` to the Silo /// @param _asset The address of the token to repay /// @param _amount amount of asset to repay, includes interests /// @return repaidAmount amount repaid /// @return burnedShare burned debt share function repay(address _asset, uint256 _amount) external returns (uint256 repaidAmount, uint256 burnedShare); /// @notice Allows to repay in behalf of borrower to execute liquidation /// @param _asset The address of the token to repay /// @param _borrower The address of the user to have debt tokens burned /// @param _amount amount of asset to repay, includes interests /// @return repaidAmount amount repaid /// @return burnedShare burned debt share function repayFor(address _asset, address _borrower, uint256 _amount) external returns (uint256 repaidAmount, uint256 burnedShare); /// @dev harvest protocol fees from an array of assets /// @return harvestedAmounts amount harvested during tx execution for each of silo asset function harvestProtocolFees() external returns (uint256[] memory harvestedAmounts); /// @notice Function to update interests for `_asset` token since the last saved state /// @param _asset The address of the token to be updated /// @return interest accrued interest function accrueInterest(address _asset) external returns (uint256 interest); /// @notice this methods does not requires to have tokens in order to liquidate user /// @dev during liquidation process, msg.sender will be notified once all collateral will be send to him /// msg.sender needs to be `IFlashLiquidationReceiver` /// @param _users array of users to liquidate /// @param _flashReceiverData this data will be forward to msg.sender on notification /// @return assets array of all processed assets (collateral + debt, including removed) /// @return receivedCollaterals receivedCollaterals[userId][assetId] => amount /// amounts of collaterals send to `_flashReceiver` /// @return shareAmountsToRepaid shareAmountsToRepaid[userId][assetId] => amount /// required amounts of debt to be repaid function flashLiquidate(address[] memory _users, bytes memory _flashReceiverData) external returns ( address[] memory assets, uint256[][] memory receivedCollaterals, uint256[][] memory shareAmountsToRepaid ); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; interface ISiloFactory { /// @notice Emitted when Silo is deployed /// @param silo address of deployed Silo /// @param asset address of asset for which Silo was deployed /// @param version version of silo implementation event NewSiloCreated(address indexed silo, address indexed asset, uint128 version); /// @notice Must be called by repository on constructor /// @param _siloRepository the SiloRepository to set function initRepository(address _siloRepository) external; /// @notice Deploys Silo /// @param _siloAsset unique asset for which Silo is deployed /// @param _version version of silo implementation /// @param _data (optional) data that may be needed during silo creation /// @return silo deployed Silo address function createSilo(address _siloAsset, uint128 _version, bytes memory _data) external returns (address silo); /// @dev just a helper method to see if address is a factory function siloFactoryPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "./ISiloFactory.sol"; import "./ITokensFactory.sol"; import "./IPriceProvidersRepository.sol"; import "./INotificationReceiver.sol"; import "./IInterestRateModel.sol"; interface ISiloRepository { /// @dev protocol fees in precision points (Solvency._PRECISION_DECIMALS), we do allow for fee == 0 struct Fees { /// @dev One time protocol fee for opening a borrow position in precision points (Solvency._PRECISION_DECIMALS) uint64 entryFee; /// @dev Protocol revenue share in interest paid in precision points (Solvency._PRECISION_DECIMALS) uint64 protocolShareFee; /// @dev Protocol share in liquidation profit in precision points (Solvency._PRECISION_DECIMALS). /// It's calculated from total collateral amount to be transferred to liquidator. uint64 protocolLiquidationFee; } struct SiloVersion { /// @dev Default version of Silo. If set to 0, it means it is not set. By default it is set to 1 uint128 byDefault; /// @dev Latest added version of Silo. If set to 0, it means it is not set. By default it is set to 1 uint128 latest; } /// @dev AssetConfig struct represents configurable parameters for each Silo struct AssetConfig { /// @dev Loan-to-Value ratio represents the maximum borrowing power of a specific collateral. /// For example, if the collateral asset has an LTV of 75%, the user can borrow up to 0.75 worth /// of quote token in the principal currency for every quote token worth of collateral. /// value uses 18 decimals eg. 100% == 1e18 /// max valid value is 1e18 so it needs storage of 60 bits uint64 maxLoanToValue; /// @dev Liquidation Threshold represents the threshold at which a borrow position will be considered /// undercollateralized and subject to liquidation for each collateral. For example, /// if a collateral has a liquidation threshold of 80%, it means that the loan will be /// liquidated when the borrowAmount value is worth 80% of the collateral value. /// value uses 18 decimals eg. 100% == 1e18 uint64 liquidationThreshold; /// @dev interest rate model address IInterestRateModel interestRateModel; } event NewDefaultMaximumLTV(uint64 defaultMaximumLTV); event NewDefaultLiquidationThreshold(uint64 defaultLiquidationThreshold); /// @notice Emitted on new Silo creation /// @param silo deployed Silo address /// @param asset unique asset for deployed Silo /// @param siloVersion version of deployed Silo event NewSilo(address indexed silo, address indexed asset, uint128 siloVersion); /// @notice Emitted when new Silo (or existing one) becomes a bridge pool (pool with only bridge tokens). /// @param pool address of the bridge pool, It can be zero address when bridge asset is removed and pool no longer /// is treated as bridge pool event BridgePool(address indexed pool); /// @notice Emitted on new bridge asset /// @param newBridgeAsset address of added bridge asset event BridgeAssetAdded(address indexed newBridgeAsset); /// @notice Emitted on removed bridge asset /// @param bridgeAssetRemoved address of removed bridge asset event BridgeAssetRemoved(address indexed bridgeAssetRemoved); /// @notice Emitted when default interest rate model is changed /// @param newModel address of new interest rate model event InterestRateModel(IInterestRateModel indexed newModel); /// @notice Emitted on price provider repository address update /// @param newProvider address of new oracle repository event PriceProvidersRepositoryUpdate( IPriceProvidersRepository indexed newProvider ); /// @notice Emitted on token factory address update /// @param newTokensFactory address of new token factory event TokensFactoryUpdate(address indexed newTokensFactory); /// @notice Emitted on router address update /// @param newRouter address of new router event RouterUpdate(address indexed newRouter); /// @notice Emitted on INotificationReceiver address update /// @param newIncentiveContract address of new INotificationReceiver event NotificationReceiverUpdate(INotificationReceiver indexed newIncentiveContract); /// @notice Emitted when new Silo version is registered /// @param factory factory address that deploys registered Silo version /// @param siloLatestVersion Silo version of registered Silo /// @param siloDefaultVersion current default Silo version event RegisterSiloVersion(address indexed factory, uint128 siloLatestVersion, uint128 siloDefaultVersion); /// @notice Emitted when Silo version is unregistered /// @param factory factory address that deploys unregistered Silo version /// @param siloVersion version that was unregistered event UnregisterSiloVersion(address indexed factory, uint128 siloVersion); /// @notice Emitted when default Silo version is updated /// @param newDefaultVersion new default version event SiloDefaultVersion(uint128 newDefaultVersion); /// @notice Emitted when default fee is updated /// @param newEntryFee new entry fee /// @param newProtocolShareFee new protocol share fee /// @param newProtocolLiquidationFee new protocol liquidation fee event FeeUpdate( uint64 newEntryFee, uint64 newProtocolShareFee, uint64 newProtocolLiquidationFee ); /// @notice Emitted when asset config is updated for a silo /// @param silo silo for which asset config is being set /// @param asset asset for which asset config is being set /// @param assetConfig new asset config event AssetConfigUpdate(address indexed silo, address indexed asset, AssetConfig assetConfig); /// @notice Emitted when silo (silo factory) version is set for asset /// @param asset asset for which asset config is being set /// @param version Silo version event VersionForAsset(address indexed asset, uint128 version); /// @param _siloAsset silo asset /// @return version of Silo that is assigned for provided asset, if not assigned it returns zero (default) function getVersionForAsset(address _siloAsset) external returns (uint128); /// @notice setter for `getVersionForAsset` mapping /// @param _siloAsset silo asset /// @param _version version of Silo that will be assigned for `_siloAsset`, zero (default) is acceptable function setVersionForAsset(address _siloAsset, uint128 _version) external; /// @notice use this method only when off-chain verification is OFF /// @dev Silo does NOT support rebase and deflationary tokens /// @param _siloAsset silo asset /// @param _siloData (optional) data that may be needed during silo creation /// @return createdSilo address of created silo function newSilo(address _siloAsset, bytes memory _siloData) external returns (address createdSilo); /// @notice use this method to deploy new version of Silo for an asset that already has Silo deployed. /// Only owner (DAO) can replace. /// @dev Silo does NOT support rebase and deflationary tokens /// @param _siloAsset silo asset /// @param _siloVersion version of silo implementation. Use 0 for default version which is fine /// for 99% of cases. /// @param _siloData (optional) data that may be needed during silo creation /// @return createdSilo address of created silo function replaceSilo( address _siloAsset, uint128 _siloVersion, bytes memory _siloData ) external returns (address createdSilo); /// @notice Set factory contract for debt and collateral tokens for each Silo asset /// @dev Callable only by owner /// @param _tokensFactory address of TokensFactory contract that deploys debt and collateral tokens function setTokensFactory(address _tokensFactory) external; /// @notice Set default fees /// @dev Callable only by owner /// @param _fees: /// - _entryFee one time protocol fee for opening a borrow position in precision points /// (Solvency._PRECISION_DECIMALS) /// - _protocolShareFee protocol revenue share in interest paid in precision points /// (Solvency._PRECISION_DECIMALS) /// - _protocolLiquidationFee protocol share in liquidation profit in precision points /// (Solvency._PRECISION_DECIMALS). It's calculated from total collateral amount to be transferred /// to liquidator. function setFees(Fees calldata _fees) external; /// @notice Set configuration for given asset in given Silo /// @dev Callable only by owner /// @param _silo Silo address for which config applies /// @param _asset asset address for which config applies /// @param _assetConfig: /// - _maxLoanToValue maximum Loan-to-Value, for details see `Repository.AssetConfig.maxLoanToValue` /// - _liquidationThreshold liquidation threshold, for details see `Repository.AssetConfig.maxLoanToValue` /// - _interestRateModel interest rate model address, for details see `Repository.AssetConfig.interestRateModel` function setAssetConfig( address _silo, address _asset, AssetConfig calldata _assetConfig ) external; /// @notice Set default interest rate model /// @dev Callable only by owner /// @param _defaultInterestRateModel default interest rate model function setDefaultInterestRateModel(IInterestRateModel _defaultInterestRateModel) external; /// @notice Set default maximum LTV /// @dev Callable only by owner /// @param _defaultMaxLTV default maximum LTV in precision points (Solvency._PRECISION_DECIMALS) function setDefaultMaximumLTV(uint64 _defaultMaxLTV) external; /// @notice Set default liquidation threshold /// @dev Callable only by owner /// @param _defaultLiquidationThreshold default liquidation threshold in precision points /// (Solvency._PRECISION_DECIMALS) function setDefaultLiquidationThreshold(uint64 _defaultLiquidationThreshold) external; /// @notice Set price provider repository /// @dev Callable only by owner /// @param _repository price provider repository address function setPriceProvidersRepository(IPriceProvidersRepository _repository) external; /// @notice Set router contract /// @dev Callable only by owner /// @param _router router address function setRouter(address _router) external; /// @notice Set NotificationReceiver contract /// @dev Callable only by owner /// @param _silo silo address for which to set `_notificationReceiver` /// @param _notificationReceiver NotificationReceiver address function setNotificationReceiver(address _silo, INotificationReceiver _notificationReceiver) external; /// @notice Adds new bridge asset /// @dev New bridge asset must be unique. Duplicates in bridge assets are not allowed. It's possible to add /// bridge asset that has been removed in the past. Note that all Silos must be synced manually. Callable /// only by owner. /// @param _newBridgeAsset bridge asset address function addBridgeAsset(address _newBridgeAsset) external; /// @notice Removes bridge asset /// @dev Note that all Silos must be synced manually. Callable only by owner. /// @param _bridgeAssetToRemove bridge asset address to be removed function removeBridgeAsset(address _bridgeAssetToRemove) external; /// @notice Registers new Silo version /// @dev User can choose which Silo version he wants to deploy. It's possible to have multiple versions of Silo. /// Callable only by owner. /// @param _factory factory contract that deploys new version of Silo /// @param _isDefault true if this version should be used as default function registerSiloVersion(ISiloFactory _factory, bool _isDefault) external; /// @notice Unregisters Silo version /// @dev Callable only by owner. /// @param _siloVersion Silo version to be unregistered function unregisterSiloVersion(uint128 _siloVersion) external; /// @notice Sets default Silo version /// @dev Callable only by owner. /// @param _defaultVersion Silo version to be set as default function setDefaultSiloVersion(uint128 _defaultVersion) external; /// @notice Check if contract address is a Silo deployment /// @param _silo address of expected Silo /// @return true if address is Silo deployment, otherwise false function isSilo(address _silo) external view returns (bool); /// @notice Get Silo address of asset /// @param _asset address of asset /// @return address of corresponding Silo deployment function getSilo(address _asset) external view returns (address); /// @notice Get Silo Factory for given version /// @param _siloVersion version of Silo implementation /// @return ISiloFactory contract that deploys Silos of given version function siloFactory(uint256 _siloVersion) external view returns (ISiloFactory); /// @notice Get debt and collateral Token Factory /// @return ITokensFactory contract that deploys debt and collateral tokens function tokensFactory() external view returns (ITokensFactory); /// @notice Get Router contract /// @return address of router contract function router() external view returns (address); /// @notice Get current bridge assets /// @dev Keep in mind that not all Silos may be synced with current bridge assets so it's possible that some /// assets in that list are not part of given Silo. /// @return address array of bridge assets function getBridgeAssets() external view returns (address[] memory); /// @notice Get removed bridge assets /// @dev Keep in mind that not all Silos may be synced with bridge assets so it's possible that some /// assets in that list are still part of given Silo. /// @return address array of bridge assets function getRemovedBridgeAssets() external view returns (address[] memory); /// @notice Get maximum LTV for asset in given Silo /// @dev If dedicated config is not set, method returns default config /// @param _silo address of Silo /// @param _asset address of an asset /// @return maximum LTV in precision points (Solvency._PRECISION_DECIMALS) function getMaximumLTV(address _silo, address _asset) external view returns (uint256); /// @notice Get Interest Rate Model address for asset in given Silo /// @dev If dedicated config is not set, method returns default config /// @param _silo address of Silo /// @param _asset address of an asset /// @return address of interest rate model function getInterestRateModel(address _silo, address _asset) external view returns (IInterestRateModel); /// @notice Get liquidation threshold for asset in given Silo /// @dev If dedicated config is not set, method returns default config /// @param _silo address of Silo /// @param _asset address of an asset /// @return liquidation threshold in precision points (Solvency._PRECISION_DECIMALS) function getLiquidationThreshold(address _silo, address _asset) external view returns (uint256); /// @notice Get incentive contract address. Incentive contracts are responsible for distributing rewards /// to debt and/or collateral token holders of given Silo /// @param _silo address of Silo /// @return incentive contract address function getNotificationReceiver(address _silo) external view returns (INotificationReceiver); /// @notice Get owner role address of Repository /// @return owner role address function owner() external view returns (address); /// @notice get PriceProvidersRepository contract that manages price providers implementations /// @return IPriceProvidersRepository address function priceProvidersRepository() external view returns (IPriceProvidersRepository); /// @dev Get protocol fee for opening a borrow position /// @return fee in precision points (Solvency._PRECISION_DECIMALS == 100%) function entryFee() external view returns (uint256); /// @dev Get protocol share fee /// @return protocol share fee in precision points (Solvency._PRECISION_DECIMALS == 100%) function protocolShareFee() external view returns (uint256); /// @dev Get protocol liquidation fee /// @return protocol liquidation fee in precision points (Solvency._PRECISION_DECIMALS == 100%) function protocolLiquidationFee() external view returns (uint256); /// @dev Checks all conditions for new silo creation and throws when not possible to create /// @param _asset address of asset for which you want to create silo /// @param _assetIsABridge bool TRUE when `_asset` is bridge asset, FALSE when it is not function ensureCanCreateSiloFor(address _asset, bool _assetIsABridge) external view; function siloRepositoryPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "./IShareToken.sol"; interface ITokensFactory { /// @notice Emitted when collateral token is deployed /// @param token address of deployed collateral token event NewShareCollateralTokenCreated(address indexed token); /// @notice Emitted when collateral token is deployed /// @param token address of deployed debt token event NewShareDebtTokenCreated(address indexed token); ///@notice Must be called by repository on constructor /// @param _siloRepository the SiloRepository to set function initRepository(address _siloRepository) external; /// @notice Deploys collateral token /// @param _name name of the token /// @param _symbol symbol of the token /// @param _asset underlying asset for which token is deployed /// @return address of deployed collateral share token function createShareCollateralToken( string memory _name, string memory _symbol, address _asset ) external returns (IShareToken); /// @notice Deploys debt token /// @param _name name of the token /// @param _symbol symbol of the token /// @param _asset underlying asset for which token is deployed /// @return address of deployed debt share token function createShareDebtToken( string memory _name, string memory _symbol, address _asset ) external returns (IShareToken); /// @dev just a helper method to see if address is a factory /// @return always true function tokensFactoryPing() external pure returns (bytes4); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "./ShareToken.sol"; import "../interfaces/ISilo.sol"; /// @title ShareCollateralToken /// @notice ERC20 compatible token representing collateral position in Silo /// @custom:security-contact [email protected] contract ShareCollateralToken is ShareToken { error SenderNotSolventAfterTransfer(); error ShareTransferNotAllowed(); /// @dev Token is always deployed for specific Silo and asset /// @param _name token name /// @param _symbol token symbol /// @param _silo Silo address for which tokens was deployed /// @param _asset asset for which this tokens was deployed constructor ( string memory _name, string memory _symbol, address _silo, address _asset ) ERC20(_name, _symbol) ShareToken(_silo, _asset) { // all setup is done in parent contracts, nothing to do here } function _afterTokenTransfer(address _sender, address _recipient, uint256 _amount) internal override { ShareToken._afterTokenTransfer(_sender, _recipient, _amount); // if we minting or burning, Silo is responsible to check all necessary conditions // make sure that _sender is solvent after transfer if (_isTransfer(_sender, _recipient) && !silo.isSolvent(_sender)) { revert SenderNotSolventAfterTransfer(); } // report mint or transfer _notifyAboutTransfer(_sender, _recipient, _amount); } function _beforeTokenTransfer(address _sender, address _recipient, uint256) internal view override { // if we minting or burning, Silo is responsible to check all necessary conditions if (!_isTransfer(_sender, _recipient)) { return; } // Silo forbids having debt and collateral position of the same asset in given Silo if (!silo.depositPossible(asset, _recipient)) revert ShareTransferNotAllowed(); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "../interfaces/IERC20R.sol"; import "../interfaces/ISilo.sol"; import "./ShareToken.sol"; /// @title ShareDebtToken /// @notice ERC20 compatible token representing debt position in Silo /// @dev It implements reversed approvals and checks solvency of recipient on transfer. /// /// It is assumed that there is no attack vector on taking someone else's debt because we don't see /// economical reason why one would do such thing. For that reason anyone can transfer owner's token /// to any recipient as long as receiving wallet approves the transfer. In other words, anyone can /// take someone else's debt without asking. /// @custom:security-contact [email protected] contract ShareDebtToken is IERC20R, ShareToken { /// @dev maps _owner => _recipient => amount mapping(address => mapping(address => uint256)) private _receiveAllowances; error OwnerIsZero(); error RecipientIsZero(); error ShareTransferNotAllowed(); error AmountExceedsAllowance(); error RecipientNotSolventAfterTransfer(); constructor ( string memory _name, string memory _symbol, address _silo, address _asset ) ERC20(_name, _symbol) ShareToken(_silo, _asset) { // all setup is done in parent contracts, nothing to do here } /// @inheritdoc IERC20R function setReceiveApproval(address owner, uint256 _amount) external virtual override { _setReceiveApproval(owner, _msgSender(), _amount); } /// @inheritdoc IERC20R function decreaseReceiveAllowance(address _owner, uint256 _subtractedValue) public virtual override { uint256 currentAllowance = _receiveAllowances[_owner][_msgSender()]; _setReceiveApproval(_owner, _msgSender(), currentAllowance - _subtractedValue); } /// @inheritdoc IERC20R function increaseReceiveAllowance(address _owner, uint256 _addedValue) public virtual override { uint256 currentAllowance = _receiveAllowances[_owner][_msgSender()]; _setReceiveApproval(_owner, _msgSender(), currentAllowance + _addedValue); } /// @inheritdoc IERC20R function receiveAllowance(address _owner, address _recipient) public view virtual override returns (uint256) { return _receiveAllowances[_owner][_recipient]; } /// @dev Set allowance /// @param _owner owner of debt token /// @param _recipient wallet that allows `_owner` to send debt to its wallet /// @param _amount amount of token allowed to be transferred function _setReceiveApproval( address _owner, address _recipient, uint256 _amount ) internal virtual { if (_owner == address(0)) revert OwnerIsZero(); if (_recipient == address(0)) revert RecipientIsZero(); _receiveAllowances[_owner][_recipient] = _amount; emit ReceiveApproval(_owner, _recipient, _amount); } function _beforeTokenTransfer(address _sender, address _recipient, uint256 _amount) internal override { // If we are minting or burning, Silo is responsible to check all necessary conditions if (!_isTransfer(_sender, _recipient)) { return; } // Silo forbids having debt and collateral position of the same asset in given Silo if (!silo.borrowPossible(asset, _recipient)) revert ShareTransferNotAllowed(); // _recipient must approve debt transfer, _sender does not have to uint256 currentAllowance = receiveAllowance(_sender, _recipient); if (currentAllowance < _amount) revert AmountExceedsAllowance(); // There can't be an underflow in the subtraction because of the previous check unchecked { // update debt allowance _setReceiveApproval(_sender, _recipient, currentAllowance - _amount); } } function _afterTokenTransfer(address _sender, address _recipient, uint256 _amount) internal override { ShareToken._afterTokenTransfer(_sender, _recipient, _amount); // if we are minting or burning, Silo is responsible to check all necessary conditions // if we are NOT minting and not burning, it means we are transferring // make sure that _recipient is solvent after transfer if (_isTransfer(_sender, _recipient) && !silo.isSolvent(_recipient)) { revert RecipientNotSolventAfterTransfer(); } // report mint or transfer _notifyAboutTransfer(_sender, _recipient, _amount); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.13; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../interfaces/ISilo.sol"; import "../interfaces/IBaseSilo.sol"; import "../interfaces/IShareToken.sol"; import "../interfaces/INotificationReceiver.sol"; /// @title ShareToken /// @notice Implements common interface for Silo tokens representing debt or collateral positions. /// @custom:security-contact [email protected] abstract contract ShareToken is ERC20, IShareToken { /// @dev minimal share amount will give us higher precision for shares calculation, /// that way losses caused by division will be reduced to acceptable level uint256 public constant MINIMUM_SHARE_AMOUNT = 1e5; /// @notice Silo address for which tokens was deployed ISilo public immutable silo; /// @notice asset for which this tokens was deployed address public immutable asset; /// @dev decimals that match the original asset decimals uint8 internal immutable _decimals; error OnlySilo(); error MinimumShareRequirement(); modifier onlySilo { if (msg.sender != address(silo)) revert OnlySilo(); _; } /// @dev Token is always deployed for specific Silo and asset /// @param _silo Silo address for which tokens was deployed /// @param _asset asset for which this tokens was deployed constructor(address _silo, address _asset) { silo = ISilo(_silo); asset = _asset; _decimals = IERC20Metadata(_asset).decimals(); } /// @inheritdoc IShareToken function mint(address _account, uint256 _amount) external onlySilo override { _mint(_account, _amount); } /// @inheritdoc IShareToken function burn(address _account, uint256 _amount) external onlySilo override { _burn(_account, _amount); } /// @inheritdoc IERC20Metadata function symbol() public view virtual override(IERC20Metadata, ERC20) returns (string memory) { return ERC20.symbol(); } /// @return decimals that match original asset decimals function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) { return _decimals; } function _afterTokenTransfer(address _sender, address _recipient, uint256) internal override virtual { // fixing precision error on mint and burn if (_isTransfer(_sender, _recipient)) { return; } uint256 total = totalSupply(); // we require minimum amount to be present from first mint // and after burning, we do not allow for small leftover if (total != 0 && total < MINIMUM_SHARE_AMOUNT) revert MinimumShareRequirement(); } /// @dev Report token transfer to incentive contract if one is set /// @param _from sender /// @param _to recipient /// @param _amount amount that was transferred function _notifyAboutTransfer(address _from, address _to, uint256 _amount) internal { INotificationReceiver notificationReceiver = IBaseSilo(silo).siloRepository().getNotificationReceiver(address(silo)); if (address(notificationReceiver) != address(0)) { // solhint-disable-next-line avoid-low-level-calls (bool success,) = address(notificationReceiver).call( abi.encodeWithSelector( INotificationReceiver.onAfterTransfer.selector, address(this), _from, _to, _amount ) ); emit NotificationSent(notificationReceiver, success); } } /// @dev checks if operation is "real" transfer /// @param _sender sender address /// @param _recipient recipient address /// @return bool true if operation is real transfer, false if it is mint or burn function _isTransfer(address _sender, address _recipient) internal pure returns (bool) { // in order this check to be true, is is required to have: // require(sender != address(0), "ERC20: transfer from the zero address"); // require(recipient != address(0), "ERC20: transfer to the zero address"); // on transfer. ERC20 has them, so we good. return _sender != address(0) && _recipient != address(0); } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"OnlySilo","type":"error"},{"inputs":[],"name":"SiloRepositoryAlreadySet","type":"error"},{"anonymous":false,"inputs":[],"name":"InitSiloRepository","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"NewShareCollateralTokenCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"NewShareDebtTokenCreated","type":"event"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_asset","type":"address"}],"name":"createShareCollateralToken","outputs":[{"internalType":"contract IShareToken","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_asset","type":"address"}],"name":"createShareDebtToken","outputs":[{"internalType":"contract IShareToken","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_repository","type":"address"}],"name":"initRepository","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"siloRepository","outputs":[{"internalType":"contract ISiloRepository","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensFactoryPing","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061330d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806304b3bbe81461005c5780636849100f14610071578063bde127181461008b578063ec3ad174146100b6578063f8f38d1b146100c9575b600080fd5b61006f61006a366004610387565b6100dc565b005b604051636849100f60e01b81526020015b60405180910390f35b60005461009e906001600160a01b031681565b6040516001600160a01b039091168152602001610082565b61009e6100c436600461044c565b61014b565b61009e6100d736600461044c565b61024d565b6000546001600160a01b031615610106576040516334a515b760e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517f62b7374e631dbf873146b0bd9f3390235a4a47128c3336ec4344c32bc28fe2929190a150565b6000805460405163025e1b9b60e31b81523360048201526001600160a01b03909116906312f0dcd890602401602060405180830381865afa158015610194573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b891906104c0565b6101d5576040516310528c6d60e11b815260040160405180910390fd5b838333846040516101e59061034f565b6101f2949392919061052f565b604051809103906000f08015801561020e573d6000803e3d6000fd5b506040519091506001600160a01b038216907f94f128ebf0749edb8bb9d165d016ce008a16bc82cbd40cc81ded2be79140d02090600090a29392505050565b6000805460405163025e1b9b60e31b81523360048201526001600160a01b03909116906312f0dcd890602401602060405180830381865afa158015610296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ba91906104c0565b6102d7576040516310528c6d60e11b815260040160405180910390fd5b838333846040516102e79061035d565b6102f4949392919061052f565b604051809103906000f080158015610310573d6000803e3d6000fd5b506040519091506001600160a01b038216907fd97e9f840332422474cda9bb0976c87735b44cda62a3fe2a4e13e2e86267181290600090a29392505050565b6117ba806200057a83390190565b6115a48062001d3483390190565b80356001600160a01b038116811461038257600080fd5b919050565b60006020828403121561039957600080fd5b6103a28261036b565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126103d057600080fd5b813567ffffffffffffffff808211156103eb576103eb6103a9565b604051601f8301601f19908116603f01168101908282118183101715610413576104136103a9565b8160405283815286602085880101111561042c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561046157600080fd5b833567ffffffffffffffff8082111561047957600080fd5b610485878388016103bf565b9450602086013591508082111561049b57600080fd5b506104a8868287016103bf565b9250506104b76040850161036b565b90509250925092565b6000602082840312156104d257600080fd5b815180151581146103a257600080fd5b6000815180845260005b81811015610508576020818501810151868301820152016104ec565b8181111561051a576000602083870101525b50601f01601f19169290920160200192915050565b60808152600061054260808301876104e2565b828103602084015261055481876104e2565b6001600160a01b0395861660408501529390941660609092019190915250939250505056fe60e06040523480156200001157600080fd5b50604051620017ba380380620017ba833981016040819052620000349162000283565b81818585816003908051906020019062000050929190620000f3565b50805162000066906004906020840190620000f3565b5050506001600160a01b03808316608052811660a08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa158015620000ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e0919062000312565b60ff1660c052506200037a945050505050565b82805462000101906200033e565b90600052602060002090601f01602090048101928262000125576000855562000170565b82601f106200014057805160ff191683800117855562000170565b8280016001018555821562000170579182015b828111156200017057825182559160200191906001019062000153565b506200017e92915062000182565b5090565b5b808211156200017e576000815560010162000183565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001c157600080fd5b81516001600160401b0380821115620001de57620001de62000199565b604051601f8301601f19908116603f0116810190828211818310171562000209576200020962000199565b816040528381526020925086838588010111156200022657600080fd5b600091505b838210156200024a57858201830151818301840152908201906200022b565b838211156200025c5760008385830101525b9695505050505050565b80516001600160a01b03811681146200027e57600080fd5b919050565b600080600080608085870312156200029a57600080fd5b84516001600160401b0380821115620002b257600080fd5b620002c088838901620001af565b95506020870151915080821115620002d757600080fd5b50620002e687828801620001af565b935050620002f76040860162000266565b9150620003076060860162000266565b905092959194509250565b6000602082840312156200032557600080fd5b815160ff811681146200033757600080fd5b9392505050565b600181811c908216806200035357607f821691505b6020821081036200037457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c0516113df620003db600039600061019e0152600081816101e20152610d2601526000818161035301528181610522015281816105fa01528181610d5601528181610e6d01528181610f80015261101701526113df6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806362221ca1116100ad5780639dc29fac116100715780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb14610302578063dd62ed3e14610315578063eb3beb291461034e57600080fd5b806362221ca11461024c57806370a082311461028557806375d68016146102ae57806380d4336e146102c157806395d89b41146102d457600080fd5b806334deadf2116100f457806334deadf2146101c857806338d52e0f146101dd578063395093511461021c5780633ca4aed01461022f57806340c10f191461023957600080fd5b806306fdde0314610131578063095ea7b31461014f57806318160ddd1461017257806323b872dd14610184578063313ce56714610197575b600080fd5b610139610375565b60405161014691906111c1565b60405180910390f35b61016261015d36600461120c565b610407565b6040519015158152602001610146565b6002545b604051908152602001610146565b610162610192366004611238565b61041d565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610146565b6101db6101d636600461120c565b6104cc565b005b6102047f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610146565b61016261022a36600461120c565b6104db565b610176620186a081565b6101db61024736600461120c565b610517565b61017661025a366004611279565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205490565b6101766102933660046112b2565b6001600160a01b031660009081526020819052604090205490565b6101db6102bc36600461120c565b61056a565b6101db6102cf36600461120c565b6105aa565b6101396105e0565b6101db6102ea36600461120c565b6105ef565b6101626102fd36600461120c565b610642565b61016261031036600461120c565b6106db565b610176610323366004611279565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102047f000000000000000000000000000000000000000000000000000000000000000081565b606060038054610384906112cf565b80601f01602080910402602001604051908101604052809291908181526020018280546103b0906112cf565b80156103fd5780601f106103d2576101008083540402835291602001916103fd565b820191906000526020600020905b8154815290600101906020018083116103e057829003601f168201915b5050505050905090565b60006104143384846106e8565b50600192915050565b600061042a84848461080d565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156104b45760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6104c185338584036106e8565b506001949350505050565b6104d78233836109f2565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161041491859061051290869061131f565b6106e8565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610560576040516310528c6d60e11b815260040160405180910390fd5b6104d78282610a99565b6001600160a01b038216600090815260056020908152604080832033808552925290912054906105a59084906105a0858561131f565b6109f2565b505050565b6001600160a01b038216600090815260056020908152604080832033808552925290912054906105a59084906105a08585611337565b60606105ea610b8c565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610638576040516310528c6d60e11b815260040160405180910390fd5b6104d78282610b9b565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156106c45760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104ab565b6106d133858584036106e8565b5060019392505050565b600061041433848461080d565b6001600160a01b03831661074a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104ab565b6001600160a01b0382166107ab5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104ab565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b0383166108715760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104ab565b6001600160a01b0382166108d35760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104ab565b6108de838383610cfc565b6001600160a01b038316600090815260208190526040902054818110156109565760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016104ab565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061098d90849061131f565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109d991815260200190565b60405180910390a36109ec848484610e32565b50505050565b6001600160a01b038316610a1957604051634269a05960e01b815260040160405180910390fd5b6001600160a01b038216610a405760405163b05313bb60e01b815260040160405180910390fd5b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902085905590518481527fa80d0efa8328d29034668db835056d5d5e5876f77ffc7bc09f1e06b2ba18b1219101610800565b6001600160a01b038216610aef5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104ab565b610afb60008383610cfc565b8060026000828254610b0d919061131f565b90915550506001600160a01b03821660009081526020819052604081208054839290610b3a90849061131f565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36104d760008383610e32565b606060048054610384906112cf565b6001600160a01b038216610bfb5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104ab565b610c0782600083610cfc565b6001600160a01b03821660009081526020819052604090205481811015610c7b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016104ab565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610caa908490611337565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36105a583600084610e32565b610d068383610f03565b610d0f57505050565b6040516379ea386160e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063f3d470c290604401602060405180830381865afa158015610d9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc1919061134e565b610dde576040516349bb6ced60e11b815260040160405180910390fd5b6001600160a01b0383811660009081526005602090815260408083209386168352929052205481811015610e25576040516303814af160e61b815260040160405180910390fd5b6109ec84848484036109f2565b610e3d838383610f2c565b610e478383610f03565b8015610eda57506040516338b51ce160e01b81526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906338b51ce190602401602060405180830381865afa158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061134e565b155b15610ef8576040516377b1921f60e11b815260040160405180910390fd5b6105a5838383610f7c565b60006001600160a01b03831615801590610f2557506001600160a01b03821615155b9392505050565b610f368383610f03565b15610f4057505050565b6000610f4b60025490565b90508015801590610f5e5750620186a081105b156109ec57604051637e442c1360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bde127186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110009190611370565b604051631a16b46360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152919091169063342d68c690602401602060405180830381865afa158015611068573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108c9190611370565b90506001600160a01b038116156109ec57604080513060248201526001600160a01b038681166044830152858116606483015260848083018690528351808403909101815260a490920183526020820180516001600160e01b0316630f1bf70d60e01b17905291516000928416916111039161138d565b6000604051808303816000865af19150503d8060008114611140576040519150601f19603f3d011682016040523d82523d6000602084013e611145565b606091505b50509050816001600160a01b03167fe367d7de03229ee9a5f0a76a230fa0c93a7f8605b676469f7df108d5e813c07682604051611186911515815260200190565b60405180910390a25050505050565b60005b838110156111b0578181015183820152602001611198565b838111156109ec5750506000910152565b60208152600082518060208401526111e0816040850160208701611195565b601f01601f19169190910160400192915050565b6001600160a01b038116811461120957600080fd5b50565b6000806040838503121561121f57600080fd5b823561122a816111f4565b946020939093013593505050565b60008060006060848603121561124d57600080fd5b8335611258816111f4565b92506020840135611268816111f4565b929592945050506040919091013590565b6000806040838503121561128c57600080fd5b8235611297816111f4565b915060208301356112a7816111f4565b809150509250929050565b6000602082840312156112c457600080fd5b8135610f25816111f4565b600181811c908216806112e357607f821691505b60208210810361130357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561133257611332611309565b500190565b60008282101561134957611349611309565b500390565b60006020828403121561136057600080fd5b81518015158114610f2557600080fd5b60006020828403121561138257600080fd5b8151610f25816111f4565b6000825161139f818460208701611195565b919091019291505056fea2646970667358221220559fbf7bdc9314a8d76b81a42c64e52f434be54493d9246122eaf111993c7f3064736f6c634300080d003360e06040523480156200001157600080fd5b50604051620015a4380380620015a4833981016040819052620000349162000283565b81818585816003908051906020019062000050929190620000f3565b50805162000066906004906020840190620000f3565b5050506001600160a01b03808316608052811660a08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa158015620000ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e0919062000312565b60ff1660c052506200037a945050505050565b82805462000101906200033e565b90600052602060002090601f01602090048101928262000125576000855562000170565b82601f106200014057805160ff191683800117855562000170565b8280016001018555821562000170579182015b828111156200017057825182559160200191906001019062000153565b506200017e92915062000182565b5090565b5b808211156200017e576000815560010162000183565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001c157600080fd5b81516001600160401b0380821115620001de57620001de62000199565b604051601f8301601f19908116603f0116810190828211818310171562000209576200020962000199565b816040528381526020925086838588010111156200022657600080fd5b600091505b838210156200024a57858201830151818301840152908201906200022b565b838211156200025c5760008385830101525b9695505050505050565b80516001600160a01b03811681146200027e57600080fd5b919050565b600080600080608085870312156200029a57600080fd5b84516001600160401b0380821115620002b257600080fd5b620002c088838901620001af565b95506020870151915080821115620002d757600080fd5b50620002e687828801620001af565b935050620002f76040860162000266565b9150620003076060860162000266565b905092959194509250565b6000602082840312156200032557600080fd5b815160ff811681146200033757600080fd5b9392505050565b600181811c908216806200035357607f821691505b6020821081036200037457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c0516111c9620003db60003960006101720152600081816101a10152610b640152600081816102b501528181610475015281816104db01528181610b9401528181610c5701528181610d6a0152610e0101526111c96000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d714610251578063a9059cbb14610264578063dd62ed3e14610277578063eb3beb29146102b057600080fd5b806340c10f19146101f857806370a082311461020d57806395d89b41146102365780639dc29fac1461023e57600080fd5b8063313ce567116100d3578063313ce5671461016b57806338d52e0f1461019c57806339509351146101db5780633ca4aed0146101ee57600080fd5b806306fdde0314610105578063095ea7b31461012357806318160ddd1461014657806323b872dd14610158575b600080fd5b61010d6102d7565b60405161011a9190610fab565b60405180910390f35b610136610131366004610ff6565b610369565b604051901515815260200161011a565b6002545b60405190815260200161011a565b610136610166366004611022565b61037f565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161011a565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161011a565b6101366101e9366004610ff6565b61042e565b61014a620186a081565b61020b610206366004610ff6565b61046a565b005b61014a61021b366004611063565b6001600160a01b031660009081526020819052604090205490565b61010d6104c1565b61020b61024c366004610ff6565b6104d0565b61013661025f366004610ff6565b610523565b610136610272366004610ff6565b6105bc565b61014a610285366004611080565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6060600380546102e6906110b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610312906110b9565b801561035f5780601f106103345761010080835404028352916020019161035f565b820191906000526020600020905b81548152906001019060200180831161034257829003601f168201915b5050505050905090565b60006103763384846105c9565b50600192915050565b600061038c8484846106ed565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156104165760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61042385338584036105c9565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610376918590610465908690611109565b6105c9565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104b3576040516310528c6d60e11b815260040160405180910390fd5b6104bd82826108d2565b5050565b60606104cb6109c5565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610519576040516310528c6d60e11b815260040160405180910390fd5b6104bd82826109d4565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156105a55760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161040d565b6105b233858584036105c9565b5060019392505050565b60006103763384846106ed565b6001600160a01b03831661062b5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161040d565b6001600160a01b03821661068c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161040d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166107515760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161040d565b6001600160a01b0382166107b35760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161040d565b6107be838383610b3a565b6001600160a01b038316600090815260208190526040902054818110156108365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161040d565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061086d908490611109565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108b991815260200190565b60405180910390a36108cc848484610c1c565b50505050565b6001600160a01b0382166109285760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161040d565b61093460008383610b3a565b80600260008282546109469190611109565b90915550506001600160a01b03821660009081526020819052604081208054839290610973908490611109565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36104bd60008383610c1c565b6060600480546102e6906110b9565b6001600160a01b038216610a345760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161040d565b610a4082600083610b3a565b6001600160a01b03821660009081526020819052604090205481811015610ab45760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161040d565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610ae3908490611121565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3610b3583600084610c1c565b505050565b610b448383610ced565b610b4d57505050565b60405163a6e08aa160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a6e08aa190604401602060405180830381865afa158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190611138565b610b35576040516349bb6ced60e11b815260040160405180910390fd5b610c27838383610d16565b610c318383610ced565b8015610cc457506040516338b51ce160e01b81526001600160a01b0384811660048301527f000000000000000000000000000000000000000000000000000000000000000016906338b51ce190602401602060405180830381865afa158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc29190611138565b155b15610ce257604051633c3b8e1b60e21b815260040160405180910390fd5b610b35838383610d66565b60006001600160a01b03831615801590610d0f57506001600160a01b03821615155b9392505050565b610d208383610ced565b15610d2a57505050565b6000610d3560025490565b90508015801590610d485750620186a081105b156108cc57604051637e442c1360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bde127186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dea919061115a565b604051631a16b46360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152919091169063342d68c690602401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e76919061115a565b90506001600160a01b038116156108cc57604080513060248201526001600160a01b038681166044830152858116606483015260848083018690528351808403909101815260a490920183526020820180516001600160e01b0316630f1bf70d60e01b1790529151600092841691610eed91611177565b6000604051808303816000865af19150503d8060008114610f2a576040519150601f19603f3d011682016040523d82523d6000602084013e610f2f565b606091505b50509050816001600160a01b03167fe367d7de03229ee9a5f0a76a230fa0c93a7f8605b676469f7df108d5e813c07682604051610f70911515815260200190565b60405180910390a25050505050565b60005b83811015610f9a578181015183820152602001610f82565b838111156108cc5750506000910152565b6020815260008251806020840152610fca816040850160208701610f7f565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610ff357600080fd5b50565b6000806040838503121561100957600080fd5b823561101481610fde565b946020939093013593505050565b60008060006060848603121561103757600080fd5b833561104281610fde565b9250602084013561105281610fde565b929592945050506040919091013590565b60006020828403121561107557600080fd5b8135610d0f81610fde565b6000806040838503121561109357600080fd5b823561109e81610fde565b915060208301356110ae81610fde565b809150509250929050565b600181811c908216806110cd57607f821691505b6020821081036110ed57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561111c5761111c6110f3565b500190565b600082821015611133576111336110f3565b500390565b60006020828403121561114a57600080fd5b81518015158114610d0f57600080fd5b60006020828403121561116c57600080fd5b8151610d0f81610fde565b60008251611189818460208701610f7f565b919091019291505056fea26469706673582212203a35ec9c8f0b286c03acefa5e4c0413ce06042fc6882b978e32b58937f2f64f064736f6c634300080d0033a2646970667358221220245eeb43586308f7a2d56c7dc33f83d6b43bcbebfe5457ebf89963475156c88d64736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100575760003560e01c806304b3bbe81461005c5780636849100f14610071578063bde127181461008b578063ec3ad174146100b6578063f8f38d1b146100c9575b600080fd5b61006f61006a366004610387565b6100dc565b005b604051636849100f60e01b81526020015b60405180910390f35b60005461009e906001600160a01b031681565b6040516001600160a01b039091168152602001610082565b61009e6100c436600461044c565b61014b565b61009e6100d736600461044c565b61024d565b6000546001600160a01b031615610106576040516334a515b760e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517f62b7374e631dbf873146b0bd9f3390235a4a47128c3336ec4344c32bc28fe2929190a150565b6000805460405163025e1b9b60e31b81523360048201526001600160a01b03909116906312f0dcd890602401602060405180830381865afa158015610194573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b891906104c0565b6101d5576040516310528c6d60e11b815260040160405180910390fd5b838333846040516101e59061034f565b6101f2949392919061052f565b604051809103906000f08015801561020e573d6000803e3d6000fd5b506040519091506001600160a01b038216907f94f128ebf0749edb8bb9d165d016ce008a16bc82cbd40cc81ded2be79140d02090600090a29392505050565b6000805460405163025e1b9b60e31b81523360048201526001600160a01b03909116906312f0dcd890602401602060405180830381865afa158015610296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ba91906104c0565b6102d7576040516310528c6d60e11b815260040160405180910390fd5b838333846040516102e79061035d565b6102f4949392919061052f565b604051809103906000f080158015610310573d6000803e3d6000fd5b506040519091506001600160a01b038216907fd97e9f840332422474cda9bb0976c87735b44cda62a3fe2a4e13e2e86267181290600090a29392505050565b6117ba806200057a83390190565b6115a48062001d3483390190565b80356001600160a01b038116811461038257600080fd5b919050565b60006020828403121561039957600080fd5b6103a28261036b565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126103d057600080fd5b813567ffffffffffffffff808211156103eb576103eb6103a9565b604051601f8301601f19908116603f01168101908282118183101715610413576104136103a9565b8160405283815286602085880101111561042c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561046157600080fd5b833567ffffffffffffffff8082111561047957600080fd5b610485878388016103bf565b9450602086013591508082111561049b57600080fd5b506104a8868287016103bf565b9250506104b76040850161036b565b90509250925092565b6000602082840312156104d257600080fd5b815180151581146103a257600080fd5b6000815180845260005b81811015610508576020818501810151868301820152016104ec565b8181111561051a576000602083870101525b50601f01601f19169290920160200192915050565b60808152600061054260808301876104e2565b828103602084015261055481876104e2565b6001600160a01b0395861660408501529390941660609092019190915250939250505056fe60e06040523480156200001157600080fd5b50604051620017ba380380620017ba833981016040819052620000349162000283565b81818585816003908051906020019062000050929190620000f3565b50805162000066906004906020840190620000f3565b5050506001600160a01b03808316608052811660a08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa158015620000ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e0919062000312565b60ff1660c052506200037a945050505050565b82805462000101906200033e565b90600052602060002090601f01602090048101928262000125576000855562000170565b82601f106200014057805160ff191683800117855562000170565b8280016001018555821562000170579182015b828111156200017057825182559160200191906001019062000153565b506200017e92915062000182565b5090565b5b808211156200017e576000815560010162000183565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001c157600080fd5b81516001600160401b0380821115620001de57620001de62000199565b604051601f8301601f19908116603f0116810190828211818310171562000209576200020962000199565b816040528381526020925086838588010111156200022657600080fd5b600091505b838210156200024a57858201830151818301840152908201906200022b565b838211156200025c5760008385830101525b9695505050505050565b80516001600160a01b03811681146200027e57600080fd5b919050565b600080600080608085870312156200029a57600080fd5b84516001600160401b0380821115620002b257600080fd5b620002c088838901620001af565b95506020870151915080821115620002d757600080fd5b50620002e687828801620001af565b935050620002f76040860162000266565b9150620003076060860162000266565b905092959194509250565b6000602082840312156200032557600080fd5b815160ff811681146200033757600080fd5b9392505050565b600181811c908216806200035357607f821691505b6020821081036200037457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c0516113df620003db600039600061019e0152600081816101e20152610d2601526000818161035301528181610522015281816105fa01528181610d5601528181610e6d01528181610f80015261101701526113df6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806362221ca1116100ad5780639dc29fac116100715780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb14610302578063dd62ed3e14610315578063eb3beb291461034e57600080fd5b806362221ca11461024c57806370a082311461028557806375d68016146102ae57806380d4336e146102c157806395d89b41146102d457600080fd5b806334deadf2116100f457806334deadf2146101c857806338d52e0f146101dd578063395093511461021c5780633ca4aed01461022f57806340c10f191461023957600080fd5b806306fdde0314610131578063095ea7b31461014f57806318160ddd1461017257806323b872dd14610184578063313ce56714610197575b600080fd5b610139610375565b60405161014691906111c1565b60405180910390f35b61016261015d36600461120c565b610407565b6040519015158152602001610146565b6002545b604051908152602001610146565b610162610192366004611238565b61041d565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610146565b6101db6101d636600461120c565b6104cc565b005b6102047f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610146565b61016261022a36600461120c565b6104db565b610176620186a081565b6101db61024736600461120c565b610517565b61017661025a366004611279565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205490565b6101766102933660046112b2565b6001600160a01b031660009081526020819052604090205490565b6101db6102bc36600461120c565b61056a565b6101db6102cf36600461120c565b6105aa565b6101396105e0565b6101db6102ea36600461120c565b6105ef565b6101626102fd36600461120c565b610642565b61016261031036600461120c565b6106db565b610176610323366004611279565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102047f000000000000000000000000000000000000000000000000000000000000000081565b606060038054610384906112cf565b80601f01602080910402602001604051908101604052809291908181526020018280546103b0906112cf565b80156103fd5780601f106103d2576101008083540402835291602001916103fd565b820191906000526020600020905b8154815290600101906020018083116103e057829003601f168201915b5050505050905090565b60006104143384846106e8565b50600192915050565b600061042a84848461080d565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156104b45760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6104c185338584036106e8565b506001949350505050565b6104d78233836109f2565b5050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161041491859061051290869061131f565b6106e8565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610560576040516310528c6d60e11b815260040160405180910390fd5b6104d78282610a99565b6001600160a01b038216600090815260056020908152604080832033808552925290912054906105a59084906105a0858561131f565b6109f2565b505050565b6001600160a01b038216600090815260056020908152604080832033808552925290912054906105a59084906105a08585611337565b60606105ea610b8c565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610638576040516310528c6d60e11b815260040160405180910390fd5b6104d78282610b9b565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156106c45760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104ab565b6106d133858584036106e8565b5060019392505050565b600061041433848461080d565b6001600160a01b03831661074a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104ab565b6001600160a01b0382166107ab5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104ab565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b0383166108715760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104ab565b6001600160a01b0382166108d35760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104ab565b6108de838383610cfc565b6001600160a01b038316600090815260208190526040902054818110156109565760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016104ab565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061098d90849061131f565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109d991815260200190565b60405180910390a36109ec848484610e32565b50505050565b6001600160a01b038316610a1957604051634269a05960e01b815260040160405180910390fd5b6001600160a01b038216610a405760405163b05313bb60e01b815260040160405180910390fd5b6001600160a01b0383811660008181526005602090815260408083209487168084529482529182902085905590518481527fa80d0efa8328d29034668db835056d5d5e5876f77ffc7bc09f1e06b2ba18b1219101610800565b6001600160a01b038216610aef5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104ab565b610afb60008383610cfc565b8060026000828254610b0d919061131f565b90915550506001600160a01b03821660009081526020819052604081208054839290610b3a90849061131f565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36104d760008383610e32565b606060048054610384906112cf565b6001600160a01b038216610bfb5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104ab565b610c0782600083610cfc565b6001600160a01b03821660009081526020819052604090205481811015610c7b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016104ab565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610caa908490611337565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36105a583600084610e32565b610d068383610f03565b610d0f57505050565b6040516379ea386160e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063f3d470c290604401602060405180830381865afa158015610d9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc1919061134e565b610dde576040516349bb6ced60e11b815260040160405180910390fd5b6001600160a01b0383811660009081526005602090815260408083209386168352929052205481811015610e25576040516303814af160e61b815260040160405180910390fd5b6109ec84848484036109f2565b610e3d838383610f2c565b610e478383610f03565b8015610eda57506040516338b51ce160e01b81526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000016906338b51ce190602401602060405180830381865afa158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061134e565b155b15610ef8576040516377b1921f60e11b815260040160405180910390fd5b6105a5838383610f7c565b60006001600160a01b03831615801590610f2557506001600160a01b03821615155b9392505050565b610f368383610f03565b15610f4057505050565b6000610f4b60025490565b90508015801590610f5e5750620186a081105b156109ec57604051637e442c1360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bde127186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110009190611370565b604051631a16b46360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152919091169063342d68c690602401602060405180830381865afa158015611068573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108c9190611370565b90506001600160a01b038116156109ec57604080513060248201526001600160a01b038681166044830152858116606483015260848083018690528351808403909101815260a490920183526020820180516001600160e01b0316630f1bf70d60e01b17905291516000928416916111039161138d565b6000604051808303816000865af19150503d8060008114611140576040519150601f19603f3d011682016040523d82523d6000602084013e611145565b606091505b50509050816001600160a01b03167fe367d7de03229ee9a5f0a76a230fa0c93a7f8605b676469f7df108d5e813c07682604051611186911515815260200190565b60405180910390a25050505050565b60005b838110156111b0578181015183820152602001611198565b838111156109ec5750506000910152565b60208152600082518060208401526111e0816040850160208701611195565b601f01601f19169190910160400192915050565b6001600160a01b038116811461120957600080fd5b50565b6000806040838503121561121f57600080fd5b823561122a816111f4565b946020939093013593505050565b60008060006060848603121561124d57600080fd5b8335611258816111f4565b92506020840135611268816111f4565b929592945050506040919091013590565b6000806040838503121561128c57600080fd5b8235611297816111f4565b915060208301356112a7816111f4565b809150509250929050565b6000602082840312156112c457600080fd5b8135610f25816111f4565b600181811c908216806112e357607f821691505b60208210810361130357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561133257611332611309565b500190565b60008282101561134957611349611309565b500390565b60006020828403121561136057600080fd5b81518015158114610f2557600080fd5b60006020828403121561138257600080fd5b8151610f25816111f4565b6000825161139f818460208701611195565b919091019291505056fea2646970667358221220559fbf7bdc9314a8d76b81a42c64e52f434be54493d9246122eaf111993c7f3064736f6c634300080d003360e06040523480156200001157600080fd5b50604051620015a4380380620015a4833981016040819052620000349162000283565b81818585816003908051906020019062000050929190620000f3565b50805162000066906004906020840190620000f3565b5050506001600160a01b03808316608052811660a08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa158015620000ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e0919062000312565b60ff1660c052506200037a945050505050565b82805462000101906200033e565b90600052602060002090601f01602090048101928262000125576000855562000170565b82601f106200014057805160ff191683800117855562000170565b8280016001018555821562000170579182015b828111156200017057825182559160200191906001019062000153565b506200017e92915062000182565b5090565b5b808211156200017e576000815560010162000183565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001c157600080fd5b81516001600160401b0380821115620001de57620001de62000199565b604051601f8301601f19908116603f0116810190828211818310171562000209576200020962000199565b816040528381526020925086838588010111156200022657600080fd5b600091505b838210156200024a57858201830151818301840152908201906200022b565b838211156200025c5760008385830101525b9695505050505050565b80516001600160a01b03811681146200027e57600080fd5b919050565b600080600080608085870312156200029a57600080fd5b84516001600160401b0380821115620002b257600080fd5b620002c088838901620001af565b95506020870151915080821115620002d757600080fd5b50620002e687828801620001af565b935050620002f76040860162000266565b9150620003076060860162000266565b905092959194509250565b6000602082840312156200032557600080fd5b815160ff811681146200033757600080fd5b9392505050565b600181811c908216806200035357607f821691505b6020821081036200037457634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c0516111c9620003db60003960006101720152600081816101a10152610b640152600081816102b501528181610475015281816104db01528181610b9401528181610c5701528181610d6a0152610e0101526111c96000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806340c10f1911610097578063a457c2d711610066578063a457c2d714610251578063a9059cbb14610264578063dd62ed3e14610277578063eb3beb29146102b057600080fd5b806340c10f19146101f857806370a082311461020d57806395d89b41146102365780639dc29fac1461023e57600080fd5b8063313ce567116100d3578063313ce5671461016b57806338d52e0f1461019c57806339509351146101db5780633ca4aed0146101ee57600080fd5b806306fdde0314610105578063095ea7b31461012357806318160ddd1461014657806323b872dd14610158575b600080fd5b61010d6102d7565b60405161011a9190610fab565b60405180910390f35b610136610131366004610ff6565b610369565b604051901515815260200161011a565b6002545b60405190815260200161011a565b610136610166366004611022565b61037f565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161011a565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161011a565b6101366101e9366004610ff6565b61042e565b61014a620186a081565b61020b610206366004610ff6565b61046a565b005b61014a61021b366004611063565b6001600160a01b031660009081526020819052604090205490565b61010d6104c1565b61020b61024c366004610ff6565b6104d0565b61013661025f366004610ff6565b610523565b610136610272366004610ff6565b6105bc565b61014a610285366004611080565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6101c37f000000000000000000000000000000000000000000000000000000000000000081565b6060600380546102e6906110b9565b80601f0160208091040260200160405190810160405280929190818152602001828054610312906110b9565b801561035f5780601f106103345761010080835404028352916020019161035f565b820191906000526020600020905b81548152906001019060200180831161034257829003601f168201915b5050505050905090565b60006103763384846105c9565b50600192915050565b600061038c8484846106ed565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156104165760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61042385338584036105c9565b506001949350505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610376918590610465908690611109565b6105c9565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104b3576040516310528c6d60e11b815260040160405180910390fd5b6104bd82826108d2565b5050565b60606104cb6109c5565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610519576040516310528c6d60e11b815260040160405180910390fd5b6104bd82826109d4565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156105a55760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161040d565b6105b233858584036105c9565b5060019392505050565b60006103763384846106ed565b6001600160a01b03831661062b5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161040d565b6001600160a01b03821661068c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161040d565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166107515760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161040d565b6001600160a01b0382166107b35760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161040d565b6107be838383610b3a565b6001600160a01b038316600090815260208190526040902054818110156108365760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161040d565b6001600160a01b0380851660009081526020819052604080822085850390559185168152908120805484929061086d908490611109565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108b991815260200190565b60405180910390a36108cc848484610c1c565b50505050565b6001600160a01b0382166109285760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161040d565b61093460008383610b3a565b80600260008282546109469190611109565b90915550506001600160a01b03821660009081526020819052604081208054839290610973908490611109565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36104bd60008383610c1c565b6060600480546102e6906110b9565b6001600160a01b038216610a345760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161040d565b610a4082600083610b3a565b6001600160a01b03821660009081526020819052604090205481811015610ab45760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161040d565b6001600160a01b0383166000908152602081905260408120838303905560028054849290610ae3908490611121565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3610b3583600084610c1c565b505050565b610b448383610ced565b610b4d57505050565b60405163a6e08aa160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a6e08aa190604401602060405180830381865afa158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff9190611138565b610b35576040516349bb6ced60e11b815260040160405180910390fd5b610c27838383610d16565b610c318383610ced565b8015610cc457506040516338b51ce160e01b81526001600160a01b0384811660048301527f000000000000000000000000000000000000000000000000000000000000000016906338b51ce190602401602060405180830381865afa158015610c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc29190611138565b155b15610ce257604051633c3b8e1b60e21b815260040160405180910390fd5b610b35838383610d66565b60006001600160a01b03831615801590610d0f57506001600160a01b03821615155b9392505050565b610d208383610ced565b15610d2a57505050565b6000610d3560025490565b90508015801590610d485750620186a081105b156108cc57604051637e442c1360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bde127186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dea919061115a565b604051631a16b46360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152919091169063342d68c690602401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e76919061115a565b90506001600160a01b038116156108cc57604080513060248201526001600160a01b038681166044830152858116606483015260848083018690528351808403909101815260a490920183526020820180516001600160e01b0316630f1bf70d60e01b1790529151600092841691610eed91611177565b6000604051808303816000865af19150503d8060008114610f2a576040519150601f19603f3d011682016040523d82523d6000602084013e610f2f565b606091505b50509050816001600160a01b03167fe367d7de03229ee9a5f0a76a230fa0c93a7f8605b676469f7df108d5e813c07682604051610f70911515815260200190565b60405180910390a25050505050565b60005b83811015610f9a578181015183820152602001610f82565b838111156108cc5750506000910152565b6020815260008251806020840152610fca816040850160208701610f7f565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610ff357600080fd5b50565b6000806040838503121561100957600080fd5b823561101481610fde565b946020939093013593505050565b60008060006060848603121561103757600080fd5b833561104281610fde565b9250602084013561105281610fde565b929592945050506040919091013590565b60006020828403121561107557600080fd5b8135610d0f81610fde565b6000806040838503121561109357600080fd5b823561109e81610fde565b915060208301356110ae81610fde565b809150509250929050565b600181811c908216806110cd57607f821691505b6020821081036110ed57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561111c5761111c6110f3565b500190565b600082821015611133576111336110f3565b500390565b60006020828403121561114a57600080fd5b81518015158114610d0f57600080fd5b60006020828403121561116c57600080fd5b8151610d0f81610fde565b60008251611189818460208701610f7f565b919091019291505056fea26469706673582212203a35ec9c8f0b286c03acefa5e4c0413ce06042fc6882b978e32b58937f2f64f064736f6c634300080d0033a2646970667358221220245eeb43586308f7a2d56c7dc33f83d6b43bcbebfe5457ebf89963475156c88d64736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.