Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multi Chain
Multichain Addresses
N/ALatest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 7791637 | 416 days 4 hrs ago | IN | Create: ConvertibleBondBox | 0 ETH | 0.15231463 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
8176564 | 352 days 11 mins ago | 0 ETH | ||||
8176552 | 352 days 15 mins ago | 0 ETH | ||||
8176552 | 352 days 15 mins ago | 0 ETH | ||||
8176552 | 352 days 15 mins ago | 0 ETH | ||||
8176550 | 352 days 15 mins ago | 0 ETH | ||||
8176550 | 352 days 15 mins ago | 0 ETH | ||||
8176550 | 352 days 15 mins ago | 0 ETH | ||||
8176550 | 352 days 15 mins ago | 0 ETH | ||||
8176547 | 352 days 16 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH | ||||
8176540 | 352 days 18 mins ago | 0 ETH |
Loading...
Loading
Contract Name:
ConvertibleBondBox
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@uniswap/lib/contracts/libraries/TransferHelper.sol"; import "../../utils/CBBImmutableArgs.sol"; import "../interfaces/IConvertibleBondBox.sol"; /** * @dev Convertible Bond Box for a ButtonTranche bond * * Invariants: * - initial Price must be <= $1.00 * - penalty ratio must be < 1.0 * - safeTranche index must not be Z-tranche * * Assumptions: * - Stabletoken has a market price of $1.00 * - ButtonToken to be used as collateral in the underlying ButtonBond rebases to $1.00 * * While it is possible to deploy a bond without the above assumptions enforced, it will produce faulty math and repayment prices */ contract ConvertibleBondBox is OwnableUpgradeable, CBBImmutableArgs, IConvertibleBondBox { // Set when reinitialized uint256 public override s_startDate; uint256 public s_initialPrice; uint256 public override s_repaidSafeSlips; // Changeable by owner uint256 public override feeBps; uint256 public constant override s_trancheGranularity = 1000; uint256 public constant override s_penaltyGranularity = 1000; uint256 public constant override s_priceGranularity = 1e8; // Denominator for basis points. Used to calculate fees uint256 public constant override BPS = 10_000; uint256 public constant override maxFeeBPS = 50; modifier afterReinitialize() { if (s_startDate == 0) { revert ConvertibleBondBoxNotStarted({ given: 0, minStartDate: block.timestamp }); } _; } modifier beforeBondMature() { if (block.timestamp >= maturityDate()) { revert BondIsMature({ currentTime: block.timestamp, maturity: maturityDate() }); } _; } modifier afterBondMature() { if (block.timestamp < maturityDate()) { revert BondNotMatureYet({ maturityDate: maturityDate(), currentTime: block.timestamp }); } _; } modifier validAmount(uint256 amount) { if (amount < 1e6) { revert MinimumInput({input: amount, reqInput: 1e6}); } _; } function initialize(address _owner) external initializer beforeBondMature { require( _owner != address(0), "ConvertibleBondBox: invalid owner address" ); // Revert if penalty too high if (penalty() > s_penaltyGranularity) { revert PenaltyTooHigh({ given: penalty(), maxPenalty: s_penaltyGranularity }); } // Set owner __Ownable_init(); transferOwnership(_owner); emit Initialized(_owner); } /** * @inheritdoc IConvertibleBondBox */ function reinitialize(uint256 _initialPrice) external reinitializer(2) onlyOwner beforeBondMature { if (_initialPrice > s_priceGranularity) revert InitialPriceTooHigh({ given: _initialPrice, maxPrice: s_priceGranularity }); if (_initialPrice == 0) revert InitialPriceIsZero({given: 0, maxPrice: s_priceGranularity}); s_initialPrice = _initialPrice; //set ConvertibleBondBox Start Date to be time when init() is called s_startDate = block.timestamp; emit ReInitialized(_initialPrice, block.timestamp); } /** * @inheritdoc IConvertibleBondBox */ function lend( address _borrower, address _lender, uint256 _stableAmount ) external override afterReinitialize beforeBondMature validAmount(_stableAmount) { uint256 price = _currentPrice(); uint256 safeSlipAmount = (_stableAmount * s_priceGranularity * trancheDecimals()) / price / stableDecimals(); uint256 zTrancheAmount = (safeSlipAmount * riskRatio()) / safeRatio(); _atomicDeposit( _borrower, _lender, _stableAmount, safeSlipAmount, zTrancheAmount ); emit Lend(_msgSender(), _borrower, _lender, _stableAmount, price); } /** * @inheritdoc IConvertibleBondBox */ function borrow( address _borrower, address _lender, uint256 _safeTrancheAmount ) external override afterReinitialize beforeBondMature validAmount(_safeTrancheAmount) { uint256 price = _currentPrice(); uint256 zTrancheAmount = (_safeTrancheAmount * riskRatio()) / safeRatio(); uint256 stableAmount = (_safeTrancheAmount * price * stableDecimals()) / s_priceGranularity / trancheDecimals(); _atomicDeposit( _borrower, _lender, stableAmount, _safeTrancheAmount, zTrancheAmount ); emit Borrow( _msgSender(), _borrower, _lender, _safeTrancheAmount, price ); } /** * @inheritdoc IConvertibleBondBox */ function currentPrice() public view override afterReinitialize returns (uint256) { return _currentPrice(); } /** * @inheritdoc IConvertibleBondBox */ function repay(uint256 _stableAmount) external override afterReinitialize validAmount(_stableAmount) { //Load into memory uint256 price = _currentPrice(); //calculate inputs for internal redeem function uint256 stableFees = (_stableAmount * feeBps) / BPS; uint256 safeTranchePayout = (_stableAmount * s_priceGranularity * trancheDecimals()) / price / stableDecimals(); uint256 riskTranchePayout = (safeTranchePayout * riskRatio()) / safeRatio(); _repay(_stableAmount, stableFees, safeTranchePayout, riskTranchePayout); emit Repay(_msgSender(), _stableAmount, riskTranchePayout, price); } /** * @inheritdoc IConvertibleBondBox */ function repayMax(uint256 _riskSlipAmount) external override afterReinitialize validAmount(_riskSlipAmount) { // Load params into memory uint256 price = _currentPrice(); // Calculate inputs for internal repay function uint256 safeTranchePayout = (_riskSlipAmount * safeRatio()) / riskRatio(); uint256 stablesOwed = (safeTranchePayout * price * stableDecimals()) / s_priceGranularity / trancheDecimals(); uint256 stableFees = (stablesOwed * feeBps) / BPS; _repay(stablesOwed, stableFees, safeTranchePayout, _riskSlipAmount); //emit event emit Repay(_msgSender(), stablesOwed, _riskSlipAmount, price); } /** * @inheritdoc IConvertibleBondBox */ function redeemRiskTranche(uint256 _riskSlipAmount) external override afterBondMature validAmount(_riskSlipAmount) { //transfer fee to owner if (feeBps > 0 && _msgSender() != owner()) { uint256 feeSlip = (_riskSlipAmount * feeBps) / BPS; riskSlip().transferFrom(_msgSender(), owner(), feeSlip); _riskSlipAmount -= feeSlip; } uint256 zTranchePayout = (_riskSlipAmount * (s_penaltyGranularity - penalty())) / (s_penaltyGranularity); //transfer Z-tranches from ConvertibleBondBox to msg.sender riskTranche().transfer(_msgSender(), zTranchePayout); riskSlip().burn(_msgSender(), _riskSlipAmount); emit RedeemRiskTranche(_msgSender(), _riskSlipAmount); } /** * @inheritdoc IConvertibleBondBox */ function redeemSafeTranche(uint256 _safeSlipAmount) external override afterBondMature validAmount(_safeSlipAmount) { //transfer fee to owner if (feeBps > 0 && _msgSender() != owner()) { uint256 feeSlip = (_safeSlipAmount * feeBps) / BPS; safeSlip().transferFrom(_msgSender(), owner(), feeSlip); _safeSlipAmount -= feeSlip; } uint256 safeSlipSupply = safeSlip().totalSupply(); //burn safe-slips safeSlip().burn(_msgSender(), _safeSlipAmount); //transfer safe-Tranche after maturity only safeTranche().transfer(_msgSender(), _safeSlipAmount); uint256 zPenaltyTotal = riskTranche().balanceOf(address(this)) - riskSlip().totalSupply(); //transfer risk-Tranche penalty after maturity only riskTranche().transfer( _msgSender(), (_safeSlipAmount * zPenaltyTotal) / (safeSlipSupply - s_repaidSafeSlips) ); emit RedeemSafeTranche(_msgSender(), _safeSlipAmount); } /** * @inheritdoc IConvertibleBondBox */ function redeemStable(uint256 _safeSlipAmount) external override validAmount(_safeSlipAmount) { //transfer safeSlips to owner if (feeBps > 0 && _msgSender() != owner()) { uint256 feeSlip = (_safeSlipAmount * feeBps) / BPS; safeSlip().transferFrom(_msgSender(), owner(), feeSlip); _safeSlipAmount -= feeSlip; } uint256 stableBalance = stableToken().balanceOf(address(this)); //transfer stables TransferHelper.safeTransfer( address(stableToken()), _msgSender(), (_safeSlipAmount * stableBalance) / (s_repaidSafeSlips) ); //burn safe-slips safeSlip().burn(_msgSender(), _safeSlipAmount); s_repaidSafeSlips -= _safeSlipAmount; emit RedeemStable(_msgSender(), _safeSlipAmount, _currentPrice()); } /** * @inheritdoc IConvertibleBondBox */ function setFee(uint256 newFeeBps) external override onlyOwner beforeBondMature { if (newFeeBps > maxFeeBPS) revert FeeTooLarge({input: newFeeBps, maximum: maxFeeBPS}); feeBps = newFeeBps; emit FeeUpdate(newFeeBps); } /** * @inheritdoc IConvertibleBondBox */ function transferOwnership(address newOwner) public override(IConvertibleBondBox, OwnableUpgradeable) onlyOwner { _transferOwnership(newOwner); } function _atomicDeposit( address _borrower, address _lender, uint256 _stableAmount, uint256 _safeSlipAmount, uint256 _riskSlipAmount ) internal { //Transfer safeTranche to ConvertibleBondBox safeTranche().transferFrom( _msgSender(), address(this), _safeSlipAmount ); //Transfer riskTranche to ConvertibleBondBox riskTranche().transferFrom( _msgSender(), address(this), _riskSlipAmount ); // //Mint safeSlips to the lender safeSlip().mint(_lender, _safeSlipAmount); // //Mint riskSlips to the borrower riskSlip().mint(_borrower, _riskSlipAmount); // // Transfer stables to borrower if (_msgSender() != _borrower) { TransferHelper.safeTransferFrom( address(stableToken()), _msgSender(), _borrower, _stableAmount ); } } function _repay( uint256 _stablesOwed, uint256 _stableFees, uint256 _safeTranchePayout, uint256 _riskTranchePayout ) internal { // Update total repaid safe slips s_repaidSafeSlips += _safeTranchePayout; // Transfer fees to owner if (feeBps > 0 && _msgSender() != owner()) { TransferHelper.safeTransferFrom( address(stableToken()), _msgSender(), owner(), _stableFees ); } // Transfers stables to CBB TransferHelper.safeTransferFrom( address(stableToken()), _msgSender(), address(this), _stablesOwed ); // Transfer safeTranches to msg.sender (increment state) safeTranche().transfer(_msgSender(), _safeTranchePayout); // Transfer riskTranches to msg.sender riskTranche().transfer(_msgSender(), _riskTranchePayout); // Burn riskSlips riskSlip().burn(_msgSender(), _riskTranchePayout); } function _currentPrice() internal view returns (uint256) { if (block.timestamp < maturityDate()) { uint256 price = s_priceGranularity - ((s_priceGranularity - s_initialPrice) * (maturityDate() - block.timestamp)) / (maturityDate() - s_startDate); return price; } else { return s_priceGranularity; } } }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title Clone /// @author zefram.eth /// @notice Provides helper functions for reading immutable args from calldata contract Clone { /// @notice Reads an immutable arg with type address /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint256 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) { uint256 offset = _getImmutableArgsOffset(); uint256 el; arr = new uint256[](arrLen); for (uint64 i = 0; i < arrLen; i++) { assembly { // solhint-disable-next-line no-inline-assembly el := calldataload(add(add(offset, argOffset), mul(i, 32))) } arr[i] = el; } return arr; } /// @notice Reads an immutable arg with type uint64 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint8 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata function _getImmutableArgsOffset() internal pure returns (uint256 offset) { // solhint-disable-next-line no-inline-assembly assembly { offset := sub( calldatasize(), add(shr(240, calldataload(sub(calldatasize(), 2))), 2) ) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove: approve failed' ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom: transferFrom failed' ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); } }
pragma solidity ^0.8.3; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@uniswap/lib/contracts/libraries/TransferHelper.sol"; import "./ITranche.sol"; struct TrancheData { ITranche token; uint256 ratio; } /** * @dev Controller for a ButtonTranche bond system */ interface IBondController { event Deposit(address from, uint256 amount, uint256 feeBps); event Mature(address caller); event RedeemMature(address user, address tranche, uint256 amount); event Redeem(address user, uint256[] amounts); event FeeUpdate(uint256 newFee); function collateralToken() external view returns (address); function tranches(uint256 i) external view returns (ITranche token, uint256 ratio); function trancheCount() external view returns (uint256 count); function feeBps() external view returns (uint256 fee); function maturityDate() external view returns (uint256 maturityDate); function isMature() external view returns (bool isMature); function creationDate() external view returns (uint256 creationDate); function totalDebt() external view returns (uint256 totalDebt); /** * @dev Deposit `amount` tokens from `msg.sender`, get tranche tokens in return * Requirements: * - `msg.sender` must have `approved` `amount` collateral tokens to this contract */ function deposit(uint256 amount) external; /** * @dev Matures the bond. Disables deposits, * fixes the redemption ratio, and distributes collateral to redemption pools * Redeems any fees collected from deposits, sending redeemed funds to the contract owner * Requirements: * - The bond is not already mature * - One of: * - `msg.sender` is owner * - `maturityDate` has passed */ function mature() external; /** * @dev Redeems some tranche tokens * Requirements: * - The bond is mature * - `msg.sender` owns at least `amount` tranche tokens from address `tranche` * - `tranche` must be a valid tranche token on this bond */ function redeemMature(address tranche, uint256 amount) external; /** * @dev Redeems a slice of tranche tokens from all tranches. * Returns collateral to the user proportionally to the amount of debt they are removing * Requirements * - The bond is not mature * - The number of `amounts` is the same as the number of tranches * - The `amounts` are in equivalent ratio to the tranche order */ function redeem(uint256[] memory amounts) external; /** * @dev Updates the fee taken on deposit to the given new fee * * Requirements * - `msg.sender` has admin role * - `newFeeBps` is in range [0, 50] */ function setFee(uint256 newFeeBps) external; }
pragma solidity ^0.8.3; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@uniswap/lib/contracts/libraries/TransferHelper.sol"; /** * @dev ERC20 token to represent a single tranche for a ButtonTranche bond * */ interface ITranche is IERC20 { /** * @dev returns the BondController address which owns this Tranche contract * It should have admin permissions to call mint, burn, and redeem functions */ function bond() external view returns (address); /** * @dev Mint `amount` tokens to `to` * Only callable by the owner (bond controller). Used to * manage bonds, specifically creating tokens upon deposit * @param to the address to mint tokens to * @param amount The amount of tokens to mint */ function mint(address to, uint256 amount) external; /** * @dev Burn `amount` tokens from `from`'s balance * Only callable by the owner (bond controller). Used to * manage bonds, specifically burning tokens upon redemption * @param from The address to burn tokens from * @param amount The amount of tokens to burn */ function burn(address from, uint256 amount) external; /** * @dev Burn `amount` tokens from `from` and return the proportional * value of the collateral token to `to` * @param from The address to burn tokens from * @param to The address to send collateral back to * @param amount The amount of tokens to burn */ function redeem( address from, address to, uint256 amount ) external; }
//SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; import "../../utils/ICBBImmutableArgs.sol"; /** * @dev Convertible Bond Box for a ButtonTranche bond */ interface IConvertibleBondBox is ICBBImmutableArgs { event Lend( address caller, address borrower, address lender, uint256 stableAmount, uint256 price ); event Borrow( address caller, address borrower, address lender, uint256 stableAmount, uint256 price ); event RedeemStable(address caller, uint256 safeSlipAmount, uint256 price); event RedeemSafeTranche(address caller, uint256 safeSlipAmount); event RedeemRiskTranche(address caller, uint256 riskSlipAmount); event Repay( address caller, uint256 stablesPaid, uint256 riskTranchePayout, uint256 price ); event Initialized(address owner); event ReInitialized(uint256 initialPrice, uint256 timestamp); event FeeUpdate(uint256 newFee); error PenaltyTooHigh(uint256 given, uint256 maxPenalty); error BondIsMature(uint256 currentTime, uint256 maturity); error InitialPriceTooHigh(uint256 given, uint256 maxPrice); error InitialPriceIsZero(uint256 given, uint256 maxPrice); error ConvertibleBondBoxNotStarted(uint256 given, uint256 minStartDate); error BondNotMatureYet(uint256 maturityDate, uint256 currentTime); error MinimumInput(uint256 input, uint256 reqInput); error FeeTooLarge(uint256 input, uint256 maximum); //Need to add getters for state variables /** * @dev Sets startdate to be block.timestamp, sets initialPrice, and takes initial atomic deposit * @param _initialPrice the initialPrice for the CBB * Requirements: * - `msg.sender` is owner */ function reinitialize(uint256 _initialPrice) external; /** * @dev Lends StableTokens for SafeSlips when provided with matching borrow collateral * @param _borrower The address to send the RiskSlip and StableTokens to * @param _lender The address to send the SafeSlips to * @param _stableAmount The amount of StableTokens to lend * Requirements: * - `msg.sender` must have `approved` `_stableAmount` stable tokens to this contract - CBB must be reinitialized */ function lend( address _borrower, address _lender, uint256 _stableAmount ) external; /** * @dev Borrows with tranches of CollateralTokens when provided with a matching amount of StableTokens * Collateral tokens get tranched and any non-convertible bond box tranches get sent back to borrower * @param _borrower The address to send the RiskSlip and StableTokens to * @param _lender The address to send the SafeSlips to * @param _safeTrancheAmount The amount of SafeTranche being borrowed against * Requirements: * - `msg.sender` must have `approved` appropriate amount of tranches of tokens to this contract - CBB must be reinitialized - must be enough stable tokens inside convertible bond box to borrow */ function borrow( address _borrower, address _lender, uint256 _safeTrancheAmount ) external; /** * @dev returns time-weighted current price for SafeSlip, with final price as $1.00 at maturity */ function currentPrice() external view returns (uint256); /** * @dev allows repayment of loan in exchange for proportional amount of SafeTranche and Z-tranche * @param _stableAmount The amount of stable-Tokens to repay with * Requirements: * - `msg.sender` must have `approved` `stableAmount` of stable tokens to this contract */ function repay(uint256 _stableAmount) external; /** * @dev allows repayment of loan in exchange for proportional amount of SafeTranche and Z-tranche * @param _riskSlipAmount The amount of riskSlips to be repaid * Requirements: * - `msg.sender` must have `approved` appropriate amount of stable tokens to this contract */ function repayMax(uint256 _riskSlipAmount) external; /** * @dev allows lender to redeem SafeSlips for SafeTranches * @param _safeSlipAmount The amount of safe-slips to redeem * Requirements: * - can only be called after Bond is Mature * - `msg.sender` must have `approved` `safeSlipAmount` of SafeSlip tokens to this contract */ function redeemSafeTranche(uint256 _safeSlipAmount) external; /** * @dev allows borrower to redeem RiskSlips for tranches (i.e. default) * @param _riskSlipAmount The amount of RiskSlips to redeem * Requirements: * - can only be called after Bond is Mature * - `msg.sender` must have `approved` `_riskSlipAmount` of RiskSlip tokens to this contract */ function redeemRiskTranche(uint256 _riskSlipAmount) external; /** * @dev allows lender to redeem SafeSlips for StableTokens * @param _safeSlipAmount The amount of SafeSlips to redeem * Requirements: * - `msg.sender` must have `approved` `safeSlipAmount` of safe-Slip tokens to this contract * - can only be called when StableTokens are present inside CBB */ function redeemStable(uint256 _safeSlipAmount) external; /** * @dev Updates the fee taken on redeem/repay to the given new fee * * Requirements * - `msg.sender` has admin role * - `newFeeBps` is in range [0, 50] */ function setFee(uint256 newFeeBps) external; /** * @dev Gets the start date */ function s_startDate() external view returns (uint256); /** * @dev Gets the total repaid safe slips to date */ function s_repaidSafeSlips() external view returns (uint256); /** * @dev Gets the tranche granularity constant */ function s_trancheGranularity() external view returns (uint256); /** * @dev Gets the penalty granularity constant */ function s_penaltyGranularity() external view returns (uint256); /** * @dev Gets the price granularity constant */ function s_priceGranularity() external view returns (uint256); /** * @dev Gets the fee basis points */ function feeBps() external view returns (uint256); /** * @dev Gets the basis points denominator constant. AKA a fee granularity constant */ function BPS() external view returns (uint256); /** * @dev Gets the max fee basis points constant. */ function maxFeeBPS() external view returns (uint256); /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) external; /** * @dev Gets the initialPrice of SafeSlip. */ function s_initialPrice() external view returns (uint256); }
pragma solidity 0.8.13; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @dev ERC20 token to represent a single slip for a bond box * */ interface ISlip is IERC20 { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev returns the bond box address which owns this slip contract * It should have admin permissions to call mint, burn, and redeem functions */ function boxOwner() external view returns (address); /** * @dev Mint `amount` tokens to `to` * Only callable by the owner. * @param to the address to mint tokens to * @param amount The amount of tokens to mint */ function mint(address to, uint256 amount) external; /** * @dev Burn `amount` tokens from `from`'s balance * Only callable by the owner. * @param from The address to burn tokens from * @param amount The amount of tokens to burn */ function burn(address from, uint256 amount) external; /** * @dev allows owner to transfer ownership to a new owner. Implemented so that factory can transfer minting/burning ability to CBB after deployment * @param newOwner The address of the CBB */ function changeOwner(address newOwner) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.13; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "clones-with-immutable-args/Clone.sol"; import "../src/interfaces/ISlip.sol"; import "./ICBBImmutableArgs.sol"; /** * @notice Defines the immutable arguments for a CBB * @dev using the clones-with-immutable-args library * we fetch args from the code section */ contract CBBImmutableArgs is Clone, ICBBImmutableArgs { /** * @inheritdoc ICBBImmutableArgs */ function bond() public pure override returns (IBondController) { return IBondController(_getArgAddress(0)); } /** * @inheritdoc ICBBImmutableArgs */ function safeSlip() public pure override returns (ISlip) { return ISlip(_getArgAddress(20)); } /** * @inheritdoc ICBBImmutableArgs */ function riskSlip() public pure override returns (ISlip) { return ISlip(_getArgAddress(40)); } /** * @inheritdoc ICBBImmutableArgs */ function penalty() public pure override returns (uint256) { return _getArgUint256(60); } /** * @inheritdoc ICBBImmutableArgs */ function collateralToken() public pure override returns (IERC20) { return IERC20(_getArgAddress(92)); } /** * @inheritdoc ICBBImmutableArgs */ function stableToken() public pure override returns (IERC20) { return IERC20(_getArgAddress(112)); } /** * @inheritdoc ICBBImmutableArgs */ function trancheIndex() public pure override returns (uint256) { return _getArgUint256(132); } /** * @inheritdoc ICBBImmutableArgs */ function maturityDate() public pure override returns (uint256) { return _getArgUint256(164); } /** * @inheritdoc ICBBImmutableArgs */ function safeTranche() public pure override returns (ITranche) { return ITranche(_getArgAddress(196)); } /** * @inheritdoc ICBBImmutableArgs */ function safeRatio() public pure override returns (uint256) { return _getArgUint256(216); } /** * @inheritdoc ICBBImmutableArgs */ function riskTranche() public pure override returns (ITranche) { return ITranche(_getArgAddress(248)); } /** * @inheritdoc ICBBImmutableArgs */ function riskRatio() public pure override returns (uint256) { return _getArgUint256(268); } /** * @inheritdoc ICBBImmutableArgs */ function trancheDecimals() public pure override returns (uint256) { return _getArgUint256(300); } /** * @inheritdoc ICBBImmutableArgs */ function stableDecimals() public pure override returns (uint256) { return _getArgUint256(332); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.13; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../src/interfaces/ISlip.sol"; import "@buttonwood-protocol/tranche/contracts/interfaces/IBondController.sol"; interface ICBBImmutableArgs { /** * @notice The bond that holds the tranches * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The underlying buttonwood bond */ function bond() external pure returns (IBondController); /** * @notice The safeSlip object * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The safeSlip Slip object */ function safeSlip() external pure returns (ISlip); /** * @notice The riskSlip object * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The riskSlip Slip object */ function riskSlip() external pure returns (ISlip); /** * @notice penalty for zslips * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The penalty ratio */ function penalty() external pure returns (uint256); /** * @notice The rebasing collateral token used to make bonds * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The rebasing collateral token object */ function collateralToken() external pure returns (IERC20); /** * @notice The stable token used to buy bonds * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The stable token object */ function stableToken() external pure returns (IERC20); /** * @notice The tranche index used to pick a safe tranche * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The index representing the tranche */ function trancheIndex() external pure returns (uint256); /** * @notice The maturity date of the underlying buttonwood bond * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The timestamp for the bond maturity */ function maturityDate() external pure returns (uint256); /** * @notice The safeTranche of the Convertible Bond Box * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The safeTranche tranche object */ function safeTranche() external pure returns (ITranche); /** * @notice The tranche ratio of the safeTranche * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The tranche ratio of the safeTranche */ function safeRatio() external pure returns (uint256); /** * @notice The riskTranche of the Convertible Bond Box * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The riskTranche tranche object */ function riskTranche() external pure returns (ITranche); /** * @notice The tranche ratio of the riskTranche * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The tranche ratio of the riskTranche */ function riskRatio() external pure returns (uint256); /** * @notice The decimals of tranche-tokens * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The decimals of tranche-tokens */ function trancheDecimals() external pure returns (uint256); /** * @notice The decimals of stable-tokens * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The decimals of stable-tokens */ function stableDecimals() external pure returns (uint256); }
{ "remappings": [ "@buttonwood-protocol/button-wrappers/=lib/button-wrappers/", "@buttonwood-protocol/tranche/=lib/tranche/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@uniswap/lib/=lib/solidity-lib/", "button-wrappers/=lib/button-wrappers/contracts/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "ds-test/=lib/clones-with-immutable-args/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solidity-lib/=lib/solidity-lib/contracts/", "solmate/=lib/solmate/src/", "tranche/=lib/tranche/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"uint256","name":"currentTime","type":"uint256"},{"internalType":"uint256","name":"maturity","type":"uint256"}],"name":"BondIsMature","type":"error"},{"inputs":[{"internalType":"uint256","name":"maturityDate","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"name":"BondNotMatureYet","type":"error"},{"inputs":[{"internalType":"uint256","name":"given","type":"uint256"},{"internalType":"uint256","name":"minStartDate","type":"uint256"}],"name":"ConvertibleBondBoxNotStarted","type":"error"},{"inputs":[{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"maximum","type":"uint256"}],"name":"FeeTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"given","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"InitialPriceIsZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"given","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"InitialPriceTooHigh","type":"error"},{"inputs":[{"internalType":"uint256","name":"input","type":"uint256"},{"internalType":"uint256","name":"reqInput","type":"uint256"}],"name":"MinimumInput","type":"error"},{"inputs":[{"internalType":"uint256","name":"given","type":"uint256"},{"internalType":"uint256","name":"maxPenalty","type":"uint256"}],"name":"PenaltyTooHigh","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"stableAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"stableAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Lend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initialPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ReInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"riskSlipAmount","type":"uint256"}],"name":"RedeemRiskTranche","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"safeSlipAmount","type":"uint256"}],"name":"RedeemSafeTranche","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"safeSlipAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"RedeemStable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"stablesPaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"riskTranchePayout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Repay","type":"event"},{"inputs":[],"name":"BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bond","outputs":[{"internalType":"contract IBondController","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_lender","type":"address"},{"internalType":"uint256","name":"_safeTrancheAmount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"address","name":"_lender","type":"address"},{"internalType":"uint256","name":"_stableAmount","type":"uint256"}],"name":"lend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maturityDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxFeeBPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"penalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_riskSlipAmount","type":"uint256"}],"name":"redeemRiskTranche","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_safeSlipAmount","type":"uint256"}],"name":"redeemSafeTranche","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_safeSlipAmount","type":"uint256"}],"name":"redeemStable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_initialPrice","type":"uint256"}],"name":"reinitialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_stableAmount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_riskSlipAmount","type":"uint256"}],"name":"repayMax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"riskRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"riskSlip","outputs":[{"internalType":"contract ISlip","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"riskTranche","outputs":[{"internalType":"contract ITranche","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"s_initialPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_penaltyGranularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_priceGranularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_repaidSafeSlips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_startDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_trancheGranularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"safeRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"safeSlip","outputs":[{"internalType":"contract ISlip","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"safeTranche","outputs":[{"internalType":"contract ITranche","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFeeBps","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"stableToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"trancheDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"trancheIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506121ab806100206000396000f3fe608060405234801561001057600080fd5b50600436106102275760003560e01c8063715018a611610130578063b2016bd4116100b8578063ec95efe31161007c578063ec95efe3146103b8578063f2fde38b146103cb578063f4bb6317146103de578063fb7fcce714610356578063ffb6c6b6146103f157600080fd5b8063b2016bd41461037a578063c4d66de814610382578063d0ab79fc14610395578063d5571f021461039d578063d59624b4146103b057600080fd5b80639d1b464a116100ff5780639d1b464a1461034e578063a1e1719f14610356578063a1eb27ff1461035f578063a9d75b2b14610367578063af259a3d1461036f57600080fd5b8063715018a614610319578063734291f5146103215780638cb59df6146103345780638da5cb5b1461033d57600080fd5b80634499739f116101b3578063591269261161018257806359126926146102e657806364c9ec6f146102ee57806369fe0e2d146102f65780636fce86ec1461030957806370fe99c51461031157600080fd5b80634499739f146102ba5780634f95d4a6146102c357806351fd7d92146102cb5780635224372c146102d357600080fd5b80632104d3fa116101fa5780632104d3fa14610285578063249d39e91461028d57806324a9d85314610296578063371fd8e61461029f5780633d13f81a146102b257600080fd5b806305ec2d4d1461022c5780630edd2ffc146102415780631965e4881461025c578063197daa3c14610265575b600080fd5b61023f61023a366004611f2c565b610404565b005b610249610586565b6040519081526020015b60405180910390f35b61024960665481565b61026d610597565b6040516001600160a01b039091168152602001610253565b6102496105a3565b61024961271081565b61024960685481565b61023f6102ad366004611f68565b6105b0565b61026d6106fe565b61024960675481565b61026d61070a565b610249610716565b61023f6102e1366004611f2c565b610723565b610249610840565b61026d61084c565b61023f610304366004611f68565b610858565b61026d6108de565b610249603281565b61023f6108ea565b61023f61032f366004611f68565b6108fe565b61024960655481565b6033546001600160a01b031661026d565b610249610a40565b6102496103e881565b610249610a76565b61026d610a83565b6102496305f5e10081565b61026d610a8f565b61023f610390366004611f81565b610a9b565b610249610c69565b61023f6103ab366004611f68565b610c75565b610249610ef1565b61023f6103c6366004611f68565b610efd565b61023f6103d9366004611f81565b61134b565b61023f6103ec366004611f68565b61135f565b61023f6103ff366004611f68565b6115c2565b606554600003610435576040516305c1866f60e31b8152600060048201524260248201526044015b60405180910390fd5b61043d610ef1565b421061046e574261044c610ef1565b6040516390563c4960e01b81526004810192909252602482015260440161042c565b80620f424081101561049f576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006104a9611716565b905060006104b56105a3565b826104be610a76565b6104cc6305f5e10088611fb9565b6104d69190611fb9565b6104e09190611fd8565b6104ea9190611fd8565b905060006104f6610840565b6104fe610716565b6105089084611fb9565b6105129190611fd8565b90506105218787878585611793565b7f1d5268be19236a4609dc83af889597769acd91008294dde29578b75e54aae997335b604080516001600160a01b039283168152828b16602082015291891690820152606081018790526080810185905260a00160405180910390a150505050505050565b6000610592603c611990565b905090565b600061059260146119b2565b600061059261014c611990565b6065546000036105dc576040516305c1866f60e31b81526000600482015242602482015260440161042c565b80620f424081101561060d576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000610617611716565b905060006127106068548561062c9190611fb9565b6106369190611fd8565b905060006106426105a3565b8361064b610a76565b6106596305f5e10089611fb9565b6106639190611fb9565b61066d9190611fd8565b6106779190611fd8565b90506000610683610840565b61068b610716565b6106959084611fb9565b61069f9190611fd8565b90506106ad868484846119d7565b6040805133815260208101889052908101829052606081018590527f2fe77b1c99aca6b022b8efc6e3e8dd1b48b30748709339b65c50ef3263443e09906080015b60405180910390a1505050505050565b600061059260f86119b2565b600061059260c46119b2565b600061059261010c611990565b60655460000361074f576040516305c1866f60e31b81526000600482015242602482015260440161042c565b610757610ef1565b4210610766574261044c610ef1565b80620f4240811015610797576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006107a1611716565b905060006107ad610840565b6107b5610716565b6107bf9086611fb9565b6107c99190611fd8565b905060006107d5610a76565b6305f5e1006107e26105a3565b6107ec8689611fb9565b6107f69190611fb9565b6108009190611fd8565b61080a9190611fd8565b90506108198787838886611793565b7f96558a334f4759f0e7c423d68c84721860bd8fbf94ddc4e55158ecb125ad04b533610544565b600061059260d8611990565b600061059260006119b2565b610860611b9f565b610868610ef1565b4210610877574261044c610ef1565b60328111156108a357604051630d67e66360e21b8152600481018290526032602482015260440161042c565b60688190556040518181527f88258d7c1f0510045362f22cdeb36a2c501ef80d7a06168881189fb8480cfe2f9060200160405180910390a150565b600061059260286119b2565b6108f2611b9f565b6108fc6000611bf9565b565b60655460000361092a576040516305c1866f60e31b81526000600482015242602482015260440161042c565b80620f424081101561095b576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000610965611716565b90506000610971610716565b610979610840565b6109839086611fb9565b61098d9190611fd8565b90506000610999610a76565b6305f5e1006109a66105a3565b6109b08686611fb9565b6109ba9190611fb9565b6109c49190611fd8565b6109ce9190611fd8565b90506000612710606854836109e39190611fb9565b6109ed9190611fd8565b90506109fb828285896119d7565b6040805133815260208101849052908101879052606081018590527f2fe77b1c99aca6b022b8efc6e3e8dd1b48b30748709339b65c50ef3263443e09906080016106ee565b6000606554600003610a6e576040516305c1866f60e31b81526000600482015242602482015260440161042c565b610592611716565b600061059261012c611990565b600061059260706119b2565b6000610592605c6119b2565b600054610100900460ff1615808015610abb5750600054600160ff909116105b80610ad55750303b158015610ad5575060005460ff166001145b610af15760405162461bcd60e51b815260040161042c90611ffa565b6000805460ff191660011790558015610b14576000805461ff0019166101001790555b610b1c610ef1565b4210610b2b574261044c610ef1565b6001600160a01b038216610b935760405162461bcd60e51b815260206004820152602960248201527f436f6e7665727469626c65426f6e64426f783a20696e76616c6964206f776e6560448201526872206164647265737360b81b606482015260840161042c565b6103e8610b9e610586565b1115610bd157610bac610586565b6040516357a5d22960e11b815260048101919091526103e8602482015260440161042c565b610bd9611c4b565b610be28261134b565b6040516001600160a01b03831681527f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e69060200160405180910390a18015610c65576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15b5050565b60006105926084611990565b80620f4240811015610ca6576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000606854118015610cc357506033546001600160a01b03163314155b15610d7b57600061271060685484610cdb9190611fb9565b610ce59190611fd8565b9050610cef610597565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b8152600401610d2993929190612048565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c919061206c565b50610d77818461208e565b9250505b6000610d85610a83565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def91906120a5565b9050610e19610dfc610a83565b33606754610e0a8588611fb9565b610e149190611fd8565b611c7a565b610e21610597565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b8152600401610e4e9291906120be565b600060405180830381600087803b158015610e6857600080fd5b505af1158015610e7c573d6000803e3d6000fd5b505050508260676000828254610e92919061208e565b909155507f9e4ef3fc4bba1bbef32633e0c0b1dddc480e43c7abbe311df6b68d507db8260b90503384610ec3611716565b604080516001600160a01b0390941684526020840192909252908201526060015b60405180910390a1505050565b600061059260a4611990565b610f05610ef1565b421015610f3757610f14610ef1565b60405163c08fb5d160e01b8152600481019190915242602482015260440161042c565b80620f4240811015610f68576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000606854118015610f8557506033546001600160a01b03163314155b1561103d57600061271060685484610f9d9190611fb9565b610fa79190611fd8565b9050610fb1610597565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b8152600401610feb93929190612048565b6020604051808303816000875af115801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e919061206c565b50611039818461208e565b9250505b6000611047610597565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a891906120a5565b90506110b2610597565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b81526004016110df9291906120be565b600060405180830381600087803b1580156110f957600080fd5b505af115801561110d573d6000803e3d6000fd5b5050505061111961070a565b6001600160a01b031663a9059cbb33856040518363ffffffff1660e01b81526004016111469291906120be565b6020604051808303816000875af1158015611165573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611189919061206c565b5060006111946108de565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906120a5565b6111fd6106fe565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015611243573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126791906120a5565b611271919061208e565b905061127b6106fe565b6001600160a01b031663a9059cbb33606754611297908661208e565b6112a18589611fb9565b6112ab9190611fd8565b6040518363ffffffff1660e01b81526004016112c89291906120be565b6020604051808303816000875af11580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b919061206c565b507f47a8b28cd001076353cc680ba0cfddac1658c00563a721f9070e52f911055abc338560405161133d9291906120be565b60405180910390a150505050565b611353611b9f565b61135c81611bf9565b50565b611367610ef1565b42101561137657610f14610ef1565b80620f42408110156113a7576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006068541180156113c457506033546001600160a01b03163314155b1561147c576000612710606854846113dc9190611fb9565b6113e69190611fd8565b90506113f06108de565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b815260040161142a93929190612048565b6020604051808303816000875af1158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d919061206c565b50611478818461208e565b9250505b60006103e8611489610586565b611495906103e861208e565b61149f9085611fb9565b6114a99190611fd8565b90506114b36106fe565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b81526004016114e09291906120be565b6020604051808303816000875af11580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611523919061206c565b5061152c6108de565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b81526004016115599291906120be565b600060405180830381600087803b15801561157357600080fd5b505af1158015611587573d6000803e3d6000fd5b505050507fbb8dc0f09f61266e8c24cf921ec5f14dff5801cc587f3e2771a053e958b401386115b33390565b84604051610ee49291906120be565b600054600290610100900460ff161580156115e4575060005460ff8083169116105b6116005760405162461bcd60e51b815260040161042c90611ffa565b6000805461ffff191660ff83161761010017905561161c611b9f565b611624610ef1565b4210611633574261044c610ef1565b6305f5e10082111561166557604051631a5bb43560e01b8152600481018390526305f5e100602482015260440161042c565b8160000361169357604051633176185360e01b8152600060048201526305f5e100602482015260440161042c565b60668290554260658190556040805184815260208101929092527f5236dc938e56da2379c94eb8610589179360af7d193b65efbf3bc59741abb3e6910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610c5c565b6000611720610ef1565b42101561178a576000606554611734610ef1565b61173e919061208e565b42611747610ef1565b611751919061208e565b606654611762906305f5e10061208e565b61176c9190611fb9565b6117769190611fd8565b611784906305f5e10061208e565b92915050565b506305f5e10090565b61179b61070a565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b81526004016117ca93929190612048565b6020604051808303816000875af11580156117e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180d919061206c565b506118166106fe565b6001600160a01b03166323b872dd3330846040518463ffffffff1660e01b815260040161184593929190612048565b6020604051808303816000875af1158015611864573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611888919061206c565b50611891610597565b6001600160a01b03166340c10f1985846040518363ffffffff1660e01b81526004016118be9291906120be565b600060405180830381600087803b1580156118d857600080fd5b505af11580156118ec573d6000803e3d6000fd5b505050506118f86108de565b6001600160a01b03166340c10f1986836040518363ffffffff1660e01b81526004016119259291906120be565b600060405180830381600087803b15801561193f57600080fd5b505af1158015611953573d6000803e3d6000fd5b50505050846001600160a01b03166119683390565b6001600160a01b03161461198957611989611981610a83565b338786611da6565b5050505050565b6000806119a7600119368181013560f01c90030190565b929092013592915050565b6000806119c9600119368181013560f01c90030190565b929092013560601c92915050565b81606760008282546119e991906120d7565b909155505060685415801590611a0a57506033546001600160a01b03163314155b15611a2d57611a2d611a1a610a83565b336033546001600160a01b031686611da6565b611a40611a38610a83565b333087611da6565b611a4861070a565b6001600160a01b031663a9059cbb33846040518363ffffffff1660e01b8152600401611a759291906120be565b6020604051808303816000875af1158015611a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab8919061206c565b50611ac16106fe565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401611aee9291906120be565b6020604051808303816000875af1158015611b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b31919061206c565b50611b3a6108de565b6001600160a01b0316639dc29fac33836040518363ffffffff1660e01b8152600401611b679291906120be565b600060405180830381600087803b158015611b8157600080fd5b505af1158015611b95573d6000803e3d6000fd5b5050505050505050565b6033546001600160a01b031633146108fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161042c565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611c725760405162461bcd60e51b815260040161042c906120ef565b6108fc611ee0565b600080846001600160a01b031663a9059cbb8585604051602401611c9f9291906120be565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611cd8919061213a565b6000604051808303816000865af19150503d8060008114611d15576040519150601f19603f3d011682016040523d82523d6000602084013e611d1a565b606091505b5091509150818015611d44575080511580611d44575080806020019051810190611d44919061206c565b6119895760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b606482015260840161042c565b600080856001600160a01b03166323b872dd868686604051602401611dcd93929190612048565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611e06919061213a565b6000604051808303816000865af19150503d8060008114611e43576040519150601f19603f3d011682016040523d82523d6000602084013e611e48565b606091505b5091509150818015611e72575080511580611e72575080806020019051810190611e72919061206c565b611ed85760405162461bcd60e51b815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604482015270185b9cd9995c919c9bdb4819985a5b1959607a1b606482015260840161042c565b505050505050565b600054610100900460ff16611f075760405162461bcd60e51b815260040161042c906120ef565b6108fc33611bf9565b80356001600160a01b0381168114611f2757600080fd5b919050565b600080600060608486031215611f4157600080fd5b611f4a84611f10565b9250611f5860208501611f10565b9150604084013590509250925092565b600060208284031215611f7a57600080fd5b5035919050565b600060208284031215611f9357600080fd5b611f9c82611f10565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615611fd357611fd3611fa3565b500290565b600082611ff557634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561207e57600080fd5b81518015158114611f9c57600080fd5b6000828210156120a0576120a0611fa3565b500390565b6000602082840312156120b757600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b600082198211156120ea576120ea611fa3565b500190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000825160005b8181101561215b5760208186018101518583015201612141565b8181111561216a576000828501525b50919091019291505056fea26469706673582212204bd427feef653db4d24cb3f2f0e558a0eaac2cba270959a99a4358071172cf4564736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102275760003560e01c8063715018a611610130578063b2016bd4116100b8578063ec95efe31161007c578063ec95efe3146103b8578063f2fde38b146103cb578063f4bb6317146103de578063fb7fcce714610356578063ffb6c6b6146103f157600080fd5b8063b2016bd41461037a578063c4d66de814610382578063d0ab79fc14610395578063d5571f021461039d578063d59624b4146103b057600080fd5b80639d1b464a116100ff5780639d1b464a1461034e578063a1e1719f14610356578063a1eb27ff1461035f578063a9d75b2b14610367578063af259a3d1461036f57600080fd5b8063715018a614610319578063734291f5146103215780638cb59df6146103345780638da5cb5b1461033d57600080fd5b80634499739f116101b3578063591269261161018257806359126926146102e657806364c9ec6f146102ee57806369fe0e2d146102f65780636fce86ec1461030957806370fe99c51461031157600080fd5b80634499739f146102ba5780634f95d4a6146102c357806351fd7d92146102cb5780635224372c146102d357600080fd5b80632104d3fa116101fa5780632104d3fa14610285578063249d39e91461028d57806324a9d85314610296578063371fd8e61461029f5780633d13f81a146102b257600080fd5b806305ec2d4d1461022c5780630edd2ffc146102415780631965e4881461025c578063197daa3c14610265575b600080fd5b61023f61023a366004611f2c565b610404565b005b610249610586565b6040519081526020015b60405180910390f35b61024960665481565b61026d610597565b6040516001600160a01b039091168152602001610253565b6102496105a3565b61024961271081565b61024960685481565b61023f6102ad366004611f68565b6105b0565b61026d6106fe565b61024960675481565b61026d61070a565b610249610716565b61023f6102e1366004611f2c565b610723565b610249610840565b61026d61084c565b61023f610304366004611f68565b610858565b61026d6108de565b610249603281565b61023f6108ea565b61023f61032f366004611f68565b6108fe565b61024960655481565b6033546001600160a01b031661026d565b610249610a40565b6102496103e881565b610249610a76565b61026d610a83565b6102496305f5e10081565b61026d610a8f565b61023f610390366004611f81565b610a9b565b610249610c69565b61023f6103ab366004611f68565b610c75565b610249610ef1565b61023f6103c6366004611f68565b610efd565b61023f6103d9366004611f81565b61134b565b61023f6103ec366004611f68565b61135f565b61023f6103ff366004611f68565b6115c2565b606554600003610435576040516305c1866f60e31b8152600060048201524260248201526044015b60405180910390fd5b61043d610ef1565b421061046e574261044c610ef1565b6040516390563c4960e01b81526004810192909252602482015260440161042c565b80620f424081101561049f576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006104a9611716565b905060006104b56105a3565b826104be610a76565b6104cc6305f5e10088611fb9565b6104d69190611fb9565b6104e09190611fd8565b6104ea9190611fd8565b905060006104f6610840565b6104fe610716565b6105089084611fb9565b6105129190611fd8565b90506105218787878585611793565b7f1d5268be19236a4609dc83af889597769acd91008294dde29578b75e54aae997335b604080516001600160a01b039283168152828b16602082015291891690820152606081018790526080810185905260a00160405180910390a150505050505050565b6000610592603c611990565b905090565b600061059260146119b2565b600061059261014c611990565b6065546000036105dc576040516305c1866f60e31b81526000600482015242602482015260440161042c565b80620f424081101561060d576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000610617611716565b905060006127106068548561062c9190611fb9565b6106369190611fd8565b905060006106426105a3565b8361064b610a76565b6106596305f5e10089611fb9565b6106639190611fb9565b61066d9190611fd8565b6106779190611fd8565b90506000610683610840565b61068b610716565b6106959084611fb9565b61069f9190611fd8565b90506106ad868484846119d7565b6040805133815260208101889052908101829052606081018590527f2fe77b1c99aca6b022b8efc6e3e8dd1b48b30748709339b65c50ef3263443e09906080015b60405180910390a1505050505050565b600061059260f86119b2565b600061059260c46119b2565b600061059261010c611990565b60655460000361074f576040516305c1866f60e31b81526000600482015242602482015260440161042c565b610757610ef1565b4210610766574261044c610ef1565b80620f4240811015610797576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006107a1611716565b905060006107ad610840565b6107b5610716565b6107bf9086611fb9565b6107c99190611fd8565b905060006107d5610a76565b6305f5e1006107e26105a3565b6107ec8689611fb9565b6107f69190611fb9565b6108009190611fd8565b61080a9190611fd8565b90506108198787838886611793565b7f96558a334f4759f0e7c423d68c84721860bd8fbf94ddc4e55158ecb125ad04b533610544565b600061059260d8611990565b600061059260006119b2565b610860611b9f565b610868610ef1565b4210610877574261044c610ef1565b60328111156108a357604051630d67e66360e21b8152600481018290526032602482015260440161042c565b60688190556040518181527f88258d7c1f0510045362f22cdeb36a2c501ef80d7a06168881189fb8480cfe2f9060200160405180910390a150565b600061059260286119b2565b6108f2611b9f565b6108fc6000611bf9565b565b60655460000361092a576040516305c1866f60e31b81526000600482015242602482015260440161042c565b80620f424081101561095b576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000610965611716565b90506000610971610716565b610979610840565b6109839086611fb9565b61098d9190611fd8565b90506000610999610a76565b6305f5e1006109a66105a3565b6109b08686611fb9565b6109ba9190611fb9565b6109c49190611fd8565b6109ce9190611fd8565b90506000612710606854836109e39190611fb9565b6109ed9190611fd8565b90506109fb828285896119d7565b6040805133815260208101849052908101879052606081018590527f2fe77b1c99aca6b022b8efc6e3e8dd1b48b30748709339b65c50ef3263443e09906080016106ee565b6000606554600003610a6e576040516305c1866f60e31b81526000600482015242602482015260440161042c565b610592611716565b600061059261012c611990565b600061059260706119b2565b6000610592605c6119b2565b600054610100900460ff1615808015610abb5750600054600160ff909116105b80610ad55750303b158015610ad5575060005460ff166001145b610af15760405162461bcd60e51b815260040161042c90611ffa565b6000805460ff191660011790558015610b14576000805461ff0019166101001790555b610b1c610ef1565b4210610b2b574261044c610ef1565b6001600160a01b038216610b935760405162461bcd60e51b815260206004820152602960248201527f436f6e7665727469626c65426f6e64426f783a20696e76616c6964206f776e6560448201526872206164647265737360b81b606482015260840161042c565b6103e8610b9e610586565b1115610bd157610bac610586565b6040516357a5d22960e11b815260048101919091526103e8602482015260440161042c565b610bd9611c4b565b610be28261134b565b6040516001600160a01b03831681527f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e69060200160405180910390a18015610c65576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15b5050565b60006105926084611990565b80620f4240811015610ca6576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000606854118015610cc357506033546001600160a01b03163314155b15610d7b57600061271060685484610cdb9190611fb9565b610ce59190611fd8565b9050610cef610597565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b8152600401610d2993929190612048565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c919061206c565b50610d77818461208e565b9250505b6000610d85610a83565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610dcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610def91906120a5565b9050610e19610dfc610a83565b33606754610e0a8588611fb9565b610e149190611fd8565b611c7a565b610e21610597565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b8152600401610e4e9291906120be565b600060405180830381600087803b158015610e6857600080fd5b505af1158015610e7c573d6000803e3d6000fd5b505050508260676000828254610e92919061208e565b909155507f9e4ef3fc4bba1bbef32633e0c0b1dddc480e43c7abbe311df6b68d507db8260b90503384610ec3611716565b604080516001600160a01b0390941684526020840192909252908201526060015b60405180910390a1505050565b600061059260a4611990565b610f05610ef1565b421015610f3757610f14610ef1565b60405163c08fb5d160e01b8152600481019190915242602482015260440161042c565b80620f4240811015610f68576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b6000606854118015610f8557506033546001600160a01b03163314155b1561103d57600061271060685484610f9d9190611fb9565b610fa79190611fd8565b9050610fb1610597565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b8152600401610feb93929190612048565b6020604051808303816000875af115801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e919061206c565b50611039818461208e565b9250505b6000611047610597565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a891906120a5565b90506110b2610597565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b81526004016110df9291906120be565b600060405180830381600087803b1580156110f957600080fd5b505af115801561110d573d6000803e3d6000fd5b5050505061111961070a565b6001600160a01b031663a9059cbb33856040518363ffffffff1660e01b81526004016111469291906120be565b6020604051808303816000875af1158015611165573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611189919061206c565b5060006111946108de565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906120a5565b6111fd6106fe565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015611243573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126791906120a5565b611271919061208e565b905061127b6106fe565b6001600160a01b031663a9059cbb33606754611297908661208e565b6112a18589611fb9565b6112ab9190611fd8565b6040518363ffffffff1660e01b81526004016112c89291906120be565b6020604051808303816000875af11580156112e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130b919061206c565b507f47a8b28cd001076353cc680ba0cfddac1658c00563a721f9070e52f911055abc338560405161133d9291906120be565b60405180910390a150505050565b611353611b9f565b61135c81611bf9565b50565b611367610ef1565b42101561137657610f14610ef1565b80620f42408110156113a7576040516308a129b160e31b815260048101829052620f4240602482015260440161042c565b60006068541180156113c457506033546001600160a01b03163314155b1561147c576000612710606854846113dc9190611fb9565b6113e69190611fd8565b90506113f06108de565b6001600160a01b03166323b872dd336033546001600160a01b0316846040518463ffffffff1660e01b815260040161142a93929190612048565b6020604051808303816000875af1158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d919061206c565b50611478818461208e565b9250505b60006103e8611489610586565b611495906103e861208e565b61149f9085611fb9565b6114a99190611fd8565b90506114b36106fe565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b81526004016114e09291906120be565b6020604051808303816000875af11580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611523919061206c565b5061152c6108de565b6001600160a01b0316639dc29fac33856040518363ffffffff1660e01b81526004016115599291906120be565b600060405180830381600087803b15801561157357600080fd5b505af1158015611587573d6000803e3d6000fd5b505050507fbb8dc0f09f61266e8c24cf921ec5f14dff5801cc587f3e2771a053e958b401386115b33390565b84604051610ee49291906120be565b600054600290610100900460ff161580156115e4575060005460ff8083169116105b6116005760405162461bcd60e51b815260040161042c90611ffa565b6000805461ffff191660ff83161761010017905561161c611b9f565b611624610ef1565b4210611633574261044c610ef1565b6305f5e10082111561166557604051631a5bb43560e01b8152600481018390526305f5e100602482015260440161042c565b8160000361169357604051633176185360e01b8152600060048201526305f5e100602482015260440161042c565b60668290554260658190556040805184815260208101929092527f5236dc938e56da2379c94eb8610589179360af7d193b65efbf3bc59741abb3e6910160405180910390a16000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001610c5c565b6000611720610ef1565b42101561178a576000606554611734610ef1565b61173e919061208e565b42611747610ef1565b611751919061208e565b606654611762906305f5e10061208e565b61176c9190611fb9565b6117769190611fd8565b611784906305f5e10061208e565b92915050565b506305f5e10090565b61179b61070a565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b81526004016117ca93929190612048565b6020604051808303816000875af11580156117e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180d919061206c565b506118166106fe565b6001600160a01b03166323b872dd3330846040518463ffffffff1660e01b815260040161184593929190612048565b6020604051808303816000875af1158015611864573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611888919061206c565b50611891610597565b6001600160a01b03166340c10f1985846040518363ffffffff1660e01b81526004016118be9291906120be565b600060405180830381600087803b1580156118d857600080fd5b505af11580156118ec573d6000803e3d6000fd5b505050506118f86108de565b6001600160a01b03166340c10f1986836040518363ffffffff1660e01b81526004016119259291906120be565b600060405180830381600087803b15801561193f57600080fd5b505af1158015611953573d6000803e3d6000fd5b50505050846001600160a01b03166119683390565b6001600160a01b03161461198957611989611981610a83565b338786611da6565b5050505050565b6000806119a7600119368181013560f01c90030190565b929092013592915050565b6000806119c9600119368181013560f01c90030190565b929092013560601c92915050565b81606760008282546119e991906120d7565b909155505060685415801590611a0a57506033546001600160a01b03163314155b15611a2d57611a2d611a1a610a83565b336033546001600160a01b031686611da6565b611a40611a38610a83565b333087611da6565b611a4861070a565b6001600160a01b031663a9059cbb33846040518363ffffffff1660e01b8152600401611a759291906120be565b6020604051808303816000875af1158015611a94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab8919061206c565b50611ac16106fe565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401611aee9291906120be565b6020604051808303816000875af1158015611b0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b31919061206c565b50611b3a6108de565b6001600160a01b0316639dc29fac33836040518363ffffffff1660e01b8152600401611b679291906120be565b600060405180830381600087803b158015611b8157600080fd5b505af1158015611b95573d6000803e3d6000fd5b5050505050505050565b6033546001600160a01b031633146108fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161042c565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611c725760405162461bcd60e51b815260040161042c906120ef565b6108fc611ee0565b600080846001600160a01b031663a9059cbb8585604051602401611c9f9291906120be565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611cd8919061213a565b6000604051808303816000865af19150503d8060008114611d15576040519150601f19603f3d011682016040523d82523d6000602084013e611d1a565b606091505b5091509150818015611d44575080511580611d44575080806020019051810190611d44919061206c565b6119895760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b606482015260840161042c565b600080856001600160a01b03166323b872dd868686604051602401611dcd93929190612048565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051611e06919061213a565b6000604051808303816000865af19150503d8060008114611e43576040519150601f19603f3d011682016040523d82523d6000602084013e611e48565b606091505b5091509150818015611e72575080511580611e72575080806020019051810190611e72919061206c565b611ed85760405162461bcd60e51b815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604482015270185b9cd9995c919c9bdb4819985a5b1959607a1b606482015260840161042c565b505050505050565b600054610100900460ff16611f075760405162461bcd60e51b815260040161042c906120ef565b6108fc33611bf9565b80356001600160a01b0381168114611f2757600080fd5b919050565b600080600060608486031215611f4157600080fd5b611f4a84611f10565b9250611f5860208501611f10565b9150604084013590509250925092565b600060208284031215611f7a57600080fd5b5035919050565b600060208284031215611f9357600080fd5b611f9c82611f10565b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615611fd357611fd3611fa3565b500290565b600082611ff557634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006020828403121561207e57600080fd5b81518015158114611f9c57600080fd5b6000828210156120a0576120a0611fa3565b500390565b6000602082840312156120b757600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b600082198211156120ea576120ea611fa3565b500190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6000825160005b8181101561215b5760208186018101518583015201612141565b8181111561216a576000828501525b50919091019291505056fea26469706673582212204bd427feef653db4d24cb3f2f0e558a0eaac2cba270959a99a4358071172cf4564736f6c634300080d0033
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.