More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 8,117 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Princip... | 21486870 | 29 hrs ago | IN | 0 ETH | 0.00114479 | ||||
Withdraw Princip... | 21486815 | 29 hrs ago | IN | 0 ETH | 0.00118913 | ||||
Permit | 21462600 | 4 days ago | IN | 0 ETH | 0.00022276 | ||||
Approve | 21306371 | 26 days ago | IN | 0 ETH | 0.00024733 | ||||
Approve | 21137233 | 50 days ago | IN | 0 ETH | 0.00050751 | ||||
Approve | 21130437 | 50 days ago | IN | 0 ETH | 0.00038542 | ||||
Approve | 21070253 | 59 days ago | IN | 0 ETH | 0.00022904 | ||||
Approve | 21042422 | 63 days ago | IN | 0 ETH | 0.00015218 | ||||
Approve | 21005776 | 68 days ago | IN | 0 ETH | 0.00023648 | ||||
Approve | 20990895 | 70 days ago | IN | 0 ETH | 0.00079818 | ||||
Approve | 20983091 | 71 days ago | IN | 0 ETH | 0.00019068 | ||||
Approve | 20946957 | 76 days ago | IN | 0 ETH | 0.00024186 | ||||
Approve | 20892325 | 84 days ago | IN | 0 ETH | 0.00023451 | ||||
Approve | 20853436 | 89 days ago | IN | 0 ETH | 0.00014997 | ||||
Approve | 20845172 | 90 days ago | IN | 0 ETH | 0.00023316 | ||||
Approve | 20842759 | 91 days ago | IN | 0 ETH | 0.00083212 | ||||
Approve | 20840189 | 91 days ago | IN | 0 ETH | 0.00028165 | ||||
Withdraw Princip... | 20689601 | 112 days ago | IN | 0 ETH | 0.00029329 | ||||
Withdraw Interes... | 20689559 | 112 days ago | IN | 0 ETH | 0.00025673 | ||||
Withdraw Interes... | 20689501 | 112 days ago | IN | 0 ETH | 0.00037081 | ||||
Withdraw Princip... | 20617085 | 122 days ago | IN | 0 ETH | 0.00025156 | ||||
Transfer | 20617085 | 122 days ago | IN | 0 ETH | 0.00004866 | ||||
Withdraw Princip... | 20617085 | 122 days ago | IN | 0 ETH | 0.00030161 | ||||
Withdraw Princip... | 20616908 | 122 days ago | IN | 0 ETH | 0.00032447 | ||||
Withdraw Princip... | 20616752 | 122 days ago | IN | 0 ETH | 0.00036031 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
13224570 | 1200 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
Tranche
Compiler Version
v0.8.0+commit.c7dfd78e
Optimization Enabled:
Yes with 7500 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./interfaces/IERC20.sol"; import "./interfaces/IWrappedPosition.sol"; import "./interfaces/ITranche.sol"; import "./interfaces/ITrancheFactory.sol"; import "./interfaces/IInterestToken.sol"; import "./libraries/ERC20Permit.sol"; import "./libraries/DateString.sol"; /// @author Element Finance /// @title Tranche contract Tranche is ERC20Permit, ITranche { IInterestToken public immutable override interestToken; IWrappedPosition public immutable position; IERC20 public immutable underlying; uint8 internal immutable _underlyingDecimals; // The outstanding amount of underlying which // can be redeemed from the contract from Principal Tokens // NOTE - we use smaller sizes so that they can be one storage slot uint128 public valueSupplied; // The total supply of interest tokens uint128 public override interestSupply; // The timestamp when tokens can be redeemed. uint256 public immutable unlockTimestamp; // The amount of slippage allowed on the Principal token redemption [0.1 basis points] uint256 internal constant _SLIPPAGE_BP = 1e13; // The speedbump variable records the first timestamp where redemption was attempted to be // performed on a tranche where loss occurred. It blocks redemptions for 48 hours after // it is triggered in order to (1) prevent atomic flash loan price manipulation (2) // give 48 hours to remediate any other loss scenario before allowing withdraws uint256 public speedbump; // Const which is 48 hours in seconds uint256 internal constant _FORTY_EIGHT_HOURS = 172800; // An event to listen for when negative interest withdraw are triggered event SpeedBumpHit(uint256 timestamp); /// @notice Constructs this contract constructor() ERC20Permit("Element Principal Token ", "eP") { // Assume the caller is the Tranche factory. ITrancheFactory trancheFactory = ITrancheFactory(msg.sender); ( address wpAddress, uint256 expiration, IInterestToken interestTokenTemp, // solhint-disable-next-line address unused ) = trancheFactory.getData(); interestToken = interestTokenTemp; IWrappedPosition wpContract = IWrappedPosition(wpAddress); position = wpContract; // Store the immutable time variables unlockTimestamp = expiration; // We use local because immutables are not readable in construction IERC20 localUnderlying = wpContract.token(); underlying = localUnderlying; // We load and store the underlying decimals uint8 localUnderlyingDecimals = localUnderlying.decimals(); _underlyingDecimals = localUnderlyingDecimals; // And set this contract to have the same _setupDecimals(localUnderlyingDecimals); } /// @notice We override the optional extra construction function from ERC20 to change names function _extraConstruction() internal override { // Assume the caller is the Tranche factory and that this is called from constructor // We have to do this double load because of the lack of flexibility in constructor ordering ITrancheFactory trancheFactory = ITrancheFactory(msg.sender); ( address wpAddress, uint256 expiration, // solhint-disable-next-line IInterestToken unused, address dateLib ) = trancheFactory.getData(); string memory strategySymbol = IWrappedPosition(wpAddress).symbol(); // Write the strategySymbol and expiration time to name and symbol // This logic was previously encoded as calling a library "DateString" // in line and directly. However even though this code is only in the constructor // it both made the code of this contract much bigger and made the factory // un deployable. So we needed to use the library as an external contract // but solidity does not have support for address to library conversions // or other support for working directly with libraries in a type safe way. // For that reason we have to use this ugly and non type safe hack to make these // contracts deployable. Since the library is an immutable in the factory // the security profile is quite similar to a standard external linked library. // We load the real storage slots of the symbol and name storage variables uint256 namePtr; uint256 symbolPtr; assembly { namePtr := name.slot symbolPtr := symbol.slot } // We then call the 'encodeAndWriteTimestamp' function on our library contract (bool success1, ) = dateLib.delegatecall( abi.encodeWithSelector( DateString.encodeAndWriteTimestamp.selector, strategySymbol, expiration, namePtr ) ); (bool success2, ) = dateLib.delegatecall( abi.encodeWithSelector( DateString.encodeAndWriteTimestamp.selector, strategySymbol, expiration, symbolPtr ) ); // Assert that both calls succeeded assert(success1 && success2); } /// @notice An aliasing of the getter for valueSupplied to improve ERC20 compatibility /// @return The number of principal tokens which exist. function totalSupply() external view returns (uint256) { return uint256(valueSupplied); } /** @notice Deposit wrapped position tokens and receive interest and Principal ERC20 tokens. If interest has already been accrued by the wrapped position tokens held in this contract, the number of Principal tokens minted is reduced in order to pay for the accrued interest. @param _amount The amount of underlying to deposit @param _destination The address to mint to @return The amount of principal and yield token minted as (pt, yt) */ function deposit(uint256 _amount, address _destination) external override returns (uint256, uint256) { // Transfer the underlying to be wrapped into the position underlying.transferFrom(msg.sender, address(position), _amount); // Now that we have funded the deposit we can call // the prefunded deposit return prefundedDeposit(_destination); } /// @notice This function calls the prefunded deposit method to /// create wrapped position tokens held by the contract. It should /// only be called when a transfer has already been made to /// the wrapped position contract of the underlying /// @param _destination The address to mint to /// @return the amount of principal and yield token minted as (pt, yt) /// @dev WARNING - The call which funds this method MUST be in the same transaction // as the call to this method or you risk loss of funds function prefundedDeposit(address _destination) public override returns (uint256, uint256) { // We check that this it is possible to deposit require(block.timestamp < unlockTimestamp, "expired"); // Since the wrapped position contract holds a balance we use the prefunded deposit method ( uint256 shares, uint256 usedUnderlying, uint256 balanceBefore ) = position.prefundedDeposit(address(this)); // The implied current value of the holding of this contract in underlying // is the balanceBefore*(usedUnderlying/shares) since (usedUnderlying/shares) // is underlying per share and balanceBefore is the balance of this contract // in position tokens before this deposit. uint256 holdingsValue = (balanceBefore * usedUnderlying) / shares; // This formula is inputUnderlying - inputUnderlying*interestPerUnderlying // Accumulated interest has its value in the interest tokens so we have to mint less // principal tokens to account for that. // NOTE - If a pool has more than 100% interest in the period this will revert on underflow // The user cannot discount the principal token enough to pay for the outstanding interest accrued. (uint256 _valueSupplied, uint256 _interestSupply) = ( uint256(valueSupplied), uint256(interestSupply) ); // We block deposits in negative interest rate regimes // The +2 allows for very small rounding errors which occur when // depositing into a tranche which is attached to a wp which has // accrued interest but the tranche has not yet accrued interest // and the first deposit into the tranche is substantially smaller // than following ones. require(_valueSupplied <= holdingsValue + 2, "E:NEG_INT"); uint256 adjustedAmount; // Have to split on the initialization case and negative interest case if (_valueSupplied > 0 && holdingsValue > _valueSupplied) { adjustedAmount = usedUnderlying - ((holdingsValue - _valueSupplied) * usedUnderlying) / _interestSupply; } else { adjustedAmount = usedUnderlying; } // We record the new input of reclaimable underlying (valueSupplied, interestSupply) = ( uint128(_valueSupplied + adjustedAmount), uint128(_interestSupply + usedUnderlying) ); // We mint interest token for each underlying provided interestToken.mint(_destination, usedUnderlying); // We mint principal token discounted by the accumulated interest. _mint(_destination, adjustedAmount); // We return the number of principal token and yield token return (adjustedAmount, usedUnderlying); } /** @notice Burn principal tokens to withdraw underlying tokens. @param _amount The number of tokens to burn. @param _destination The address to send the underlying too @return The number of underlying tokens released @dev This method will return 1 underlying for 1 principal except when interest is negative, in which case the principal tokens is redeemable pro rata for the assets controlled by this vault. Also note: Redemption has the possibility of at most _SLIPPAGE_BP numerical error on each redemption so each principal token may occasionally redeem for less than 1 unit of underlying. Max loss defaults to 0.1 BP ie 0.001% loss */ function withdrawPrincipal(uint256 _amount, address _destination) external override returns (uint256) { // No redemptions before unlock require(block.timestamp >= unlockTimestamp, "E:Not Expired"); // If the speedbump == 0 it's never been hit so we don't need // to change the withdraw rate. uint256 localSpeedbump = speedbump; uint256 withdrawAmount = _amount; uint256 localSupply = uint256(valueSupplied); if (localSpeedbump != 0) { // Load the assets we have in this vault uint256 holdings = position.balanceOfUnderlying(address(this)); // If we check and the interest rate is no longer negative then we // allow normal 1 to 1 withdraws [even if the speedbump was hit less // than 48 hours ago, to prevent possible griefing] if (holdings < localSupply) { // We allow the user to only withdraw their percent of holdings // NOTE - Because of the discounting mechanics this causes account loss // percentages to be slightly perturbed from overall loss. // ie: tokens holders who join when interest has accumulated // will get slightly higher percent loss than those who joined earlier // in the case of loss at the end of the period. Biases are very // small except in extreme cases. withdrawAmount = (_amount * holdings) / localSupply; // If the interest rate is still negative and we are not 48 hours after // speedbump being set we revert require( localSpeedbump + _FORTY_EIGHT_HOURS < block.timestamp, "E:Early" ); } } // Burn from the sender _burn(msg.sender, _amount); // Remove these principal token from the interest calculations for future interest redemptions valueSupplied = uint128(localSupply) - uint128(_amount); // Load the share balance of the vault before withdrawing [gas note - both the smart // contract and share value is warmed so this is actually quite a cheap lookup] uint256 shareBalanceBefore = position.balanceOf(address(this)); // Calculate the min output uint256 minOutput = withdrawAmount - (withdrawAmount * _SLIPPAGE_BP) / 1e18; // We make the actual withdraw from the position. (uint256 actualWithdraw, uint256 sharesBurned) = position .withdrawUnderlying(_destination, withdrawAmount, minOutput); // At this point we check that the implied contract holdings before this withdraw occurred // are more than enough to redeem all of the principal tokens for underlying ie that no // loss has happened. uint256 balanceBefore = (shareBalanceBefore * actualWithdraw) / sharesBurned; if (balanceBefore < localSupply) { // Require that that the speedbump has been set. require(localSpeedbump != 0, "E:NEG_INT"); // This assert should be very difficult to hit because it is checked above // but may be possible with complex reentrancy. assert(localSpeedbump + _FORTY_EIGHT_HOURS < block.timestamp); } return (actualWithdraw); } /// @notice This function allows someone to trigger the speedbump and eventually allow /// pro rata withdraws function hitSpeedbump() external { // We only allow setting the speedbump once require(speedbump == 0, "E:AlreadySet"); // We only allow setting it when withdraws can happen require(block.timestamp >= unlockTimestamp, "E:Not Expired"); // We require that the total holds are less than the supply of // principal token we need to redeem uint256 totalHoldings = position.balanceOfUnderlying(address(this)); if (totalHoldings < valueSupplied) { // We emit a notification so that if a speedbump is hit the community // can investigate. // Note - this is a form of defense mechanism because any flash loan // attack must be public for at least 48 hours before it has // affects. emit SpeedBumpHit(block.timestamp); // Set the speedbump speedbump = block.timestamp; } else { revert("E:NoLoss"); } } /** @notice Burn interest tokens to withdraw underlying tokens. @param _amount The number of interest tokens to burn. @param _destination The address to send the result to @return The number of underlying token released @dev Due to slippage the redemption may receive up to _SLIPPAGE_BP less in output compared to the floating rate. */ function withdrawInterest(uint256 _amount, address _destination) external override returns (uint256) { require(block.timestamp >= unlockTimestamp, "E:Not Expired"); // Burn tokens from the sender interestToken.burn(msg.sender, _amount); // Load the underlying value of this contract uint256 underlyingValueLocked = position.balanceOfUnderlying( address(this) ); // Load a stack variable to avoid future sloads (uint256 _valueSupplied, uint256 _interestSupply) = ( uint256(valueSupplied), uint256(interestSupply) ); // Interest is value locked minus current value uint256 interest = underlyingValueLocked > _valueSupplied ? underlyingValueLocked - _valueSupplied : 0; // The redemption amount is the interest per token times the amount uint256 redemptionAmount = (interest * _amount) / _interestSupply; uint256 minRedemption = redemptionAmount - (redemptionAmount * _SLIPPAGE_BP) / 1e18; // Store that we reduced the supply interestSupply = uint128(_interestSupply - _amount); // Redeem position tokens for underlying (uint256 redemption, ) = position.withdrawUnderlying( _destination, redemptionAmount, minRedemption ); return (redemption); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; interface IERC20 { function symbol() external view returns (string memory); function balanceOf(address account) external view returns (uint256); // Note this is non standard but nearly all ERC20 have exposed decimal functions function decimals() external view returns (uint8); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./IERC20Permit.sol"; import "./IERC20.sol"; interface IWrappedPosition is IERC20Permit { function token() external view returns (IERC20); function balanceOfUnderlying(address who) external view returns (uint256); function getSharesToUnderlying(uint256 shares) external view returns (uint256); function deposit(address sender, uint256 amount) external returns (uint256); function withdraw( address sender, uint256 _shares, uint256 _minUnderlying ) external returns (uint256); function withdrawUnderlying( address _destination, uint256 _amount, uint256 _minUnderlying ) external returns (uint256, uint256); function prefundedDeposit(address _destination) external returns ( uint256, uint256, uint256 ); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./IERC20Permit.sol"; import "./IInterestToken.sol"; interface ITranche is IERC20Permit { function deposit(uint256 _shares, address destination) external returns (uint256, uint256); function prefundedDeposit(address _destination) external returns (uint256, uint256); function withdrawPrincipal(uint256 _amount, address _destination) external returns (uint256); function withdrawInterest(uint256 _amount, address _destination) external returns (uint256); function interestToken() external view returns (IInterestToken); function interestSupply() external view returns (uint128); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "../InterestToken.sol"; import "../libraries/DateString.sol"; interface ITrancheFactory { function getData() external returns ( address, uint256, InterestToken, address ); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./IERC20Permit.sol"; interface IInterestToken is IERC20Permit { function mint(address _account, uint256 _amount) external; function burn(address _account, uint256 _amount) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "../interfaces/IERC20Permit.sol"; // This default erc20 library is designed for max efficiency and security. // WARNING: By default it does not include totalSupply which breaks the ERC20 standard // to use a fully standard compliant ERC20 use 'ERC20PermitWithSupply" abstract contract ERC20Permit is IERC20Permit { // --- ERC20 Data --- // The name of the erc20 token string public name; // The symbol of the erc20 token string public override symbol; // The decimals of the erc20 token, should default to 18 for new tokens uint8 public override decimals; // A mapping which tracks user token balances mapping(address => uint256) public override balanceOf; // A mapping which tracks which addresses a user allows to move their tokens mapping(address => mapping(address => uint256)) public override allowance; // A mapping which tracks the permit signature nonces for users mapping(address => uint256) public override nonces; // --- EIP712 niceties --- // solhint-disable-next-line var-name-mixedcase bytes32 public override DOMAIN_SEPARATOR; // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; /// @notice Initializes the erc20 contract /// @param name_ the value 'name' will be set to /// @param symbol_ the value 'symbol' will be set to /// @dev decimals default to 18 and must be reset by an inheriting contract for /// non standard decimal values constructor(string memory name_, string memory symbol_) { // Set the state variables name = name_; symbol = symbol_; decimals = 18; // By setting these addresses to 0 attempting to execute a transfer to // either of them will revert. This is a gas efficient way to prevent // a common user mistake where they transfer to the token address. // These values are not considered 'real' tokens and so are not included // in 'total supply' which only contains minted tokens. balanceOf[address(0)] = type(uint256).max; balanceOf[address(this)] = type(uint256).max; // Optional extra state manipulation _extraConstruction(); // Computes the EIP 712 domain separator which prevents user signed messages for // this contract to be replayed in other contracts. // https://eips.ethereum.org/EIPS/eip-712 DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), keccak256(bytes(name)), keccak256(bytes("1")), block.chainid, address(this) ) ); } /// @notice An optional override function to execute and change state before immutable assignment function _extraConstruction() internal virtual {} // --- Token --- /// @notice Allows a token owner to send tokens to another address /// @param recipient The address which will be credited with the tokens /// @param amount The amount user token to send /// @return returns true on success, reverts on failure so cannot return false. /// @dev transfers to this contract address or 0 will fail function transfer(address recipient, uint256 amount) public virtual override returns (bool) { // We forward this call to 'transferFrom' return transferFrom(msg.sender, recipient, amount); } /// @notice Transfers an amount of erc20 from a spender to a receipt /// @param spender The source of the ERC20 tokens /// @param recipient The destination of the ERC20 tokens /// @param amount the number of tokens to send /// @return returns true on success and reverts on failure /// @dev will fail transfers which send funds to this contract or 0 function transferFrom( address spender, address recipient, uint256 amount ) public virtual override returns (bool) { // Load balance and allowance uint256 balance = balanceOf[spender]; require(balance >= amount, "ERC20: insufficient-balance"); // We potentially have to change allowances if (spender != msg.sender) { // Loading the allowance in the if block prevents vanilla transfers // from paying for the sload. uint256 allowed = allowance[spender][msg.sender]; // If the allowance is max we do not reduce it // Note - This means that max allowances will be more gas efficient // by not requiring a sstore on 'transferFrom' if (allowed != type(uint256).max) { require(allowed >= amount, "ERC20: insufficient-allowance"); allowance[spender][msg.sender] = allowed - amount; } } // Update the balances balanceOf[spender] = balance - amount; // Note - In the constructor we initialize the 'balanceOf' of address 0 and // the token address to uint256.max and so in 8.0 transfers to those // addresses revert on this step. balanceOf[recipient] = balanceOf[recipient] + amount; // Emit the needed event emit Transfer(spender, recipient, amount); // Return that this call succeeded return true; } /// @notice This internal minting function allows inheriting contracts /// to mint tokens in the way they wish. /// @param account the address which will receive the token. /// @param amount the amount of token which they will receive /// @dev This function is virtual so that it can be overridden, if you /// are reviewing this contract for security you should ensure to /// check for overrides function _mint(address account, uint256 amount) internal virtual { // Add tokens to the account balanceOf[account] = balanceOf[account] + amount; // Emit an event to track the minting emit Transfer(address(0), account, amount); } /// @notice This internal burning function allows inheriting contracts to /// burn tokens in the way they see fit. /// @param account the account to remove tokens from /// @param amount the amount of tokens to remove /// @dev This function is virtual so that it can be overridden, if you /// are reviewing this contract for security you should ensure to /// check for overrides function _burn(address account, uint256 amount) internal virtual { // Reduce the balance of the account balanceOf[account] = balanceOf[account] - amount; // Emit an event tracking transfers emit Transfer(account, address(0), amount); } /// @notice This function allows a user to approve an account which can transfer /// tokens on their behalf. /// @param account The account which will be approve to transfer tokens /// @param amount The approval amount, if set to uint256.max the allowance does not go down on transfers. /// @return returns true for compatibility with the ERC20 standard function approve(address account, uint256 amount) public virtual override returns (bool) { // Set the senders allowance for account to amount allowance[msg.sender][account] = amount; // Emit an event to track approvals emit Approval(msg.sender, account, amount); return true; } /// @notice This function allows a caller who is not the owner of an account to execute the functionality of 'approve' with the owners signature. /// @param owner the owner of the account which is having the new approval set /// @param spender the address which will be allowed to spend owner's tokens /// @param value the new allowance value /// @param deadline the timestamp which the signature must be submitted by to be valid /// @param v Extra ECDSA data which allows public key recovery from signature assumed to be 27 or 28 /// @param r The r component of the ECDSA signature /// @param s The s component of the ECDSA signature /// @dev The signature for this function follows EIP 712 standard and should be generated with the /// eth_signTypedData JSON RPC call instead of the eth_sign JSON RPC call. If using out of date /// parity signing libraries the v component may need to be adjusted. Also it is very rare but possible /// for v to be other values, those values are not supported. function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { // The EIP 712 digest for this function bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, value, nonces[owner], deadline ) ) ) ); // Require that the owner is not zero require(owner != address(0), "ERC20: invalid-address-0"); // Require that we have a valid signature from the owner require(owner == ecrecover(digest, v, r, s), "ERC20: invalid-permit"); // Require that the signature is not expired require( deadline == 0 || block.timestamp <= deadline, "ERC20: permit-expired" ); // Format the signature to the default format require( uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ERC20: invalid signature 's' value" ); // Increment the signature nonce to prevent replay nonces[owner]++; // Set the allowance to the new value allowance[owner][spender] = value; // Emit an approval event to be able to track this happening emit Approval(owner, spender, value); } /// @notice Internal function which allows inheriting contract to set custom decimals /// @param decimals_ the new decimal value function _setupDecimals(uint8 decimals_) internal { // Set the decimals decimals = decimals_; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; library DateString { uint256 public constant SECONDS_PER_DAY = 24 * 60 * 60; uint256 public constant SECONDS_PER_HOUR = 60 * 60; uint256 public constant SECONDS_PER_MINUTE = 60; int256 public constant OFFSET19700101 = 2440588; // This function was forked from https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary // ------------------------------------------------------------------------ // Calculate year/month/day from the number of days since 1970/01/01 using // the date conversion algorithm from // http://aa.usno.navy.mil/faq/docs/JD_Formula.php // and adding the offset 2440588 so that 1970/01/01 is day 0 // // int L = days + 68569 + offset // int N = 4 * L / 146097 // L = L - (146097 * N + 3) / 4 // year = 4000 * (L + 1) / 1461001 // L = L - 1461 * year / 4 + 31 // month = 80 * L / 2447 // dd = L - 2447 * month / 80 // L = month / 11 // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ // solhint-disable-next-line private-vars-leading-underscore function _daysToDate(uint256 _days) internal pure returns ( uint256 year, uint256 month, uint256 day ) { int256 __days = int256(_days); // solhint-disable-next-line var-name-mixedcase int256 L = __days + 68569 + OFFSET19700101; // solhint-disable-next-line var-name-mixedcase int256 N = (4 * L) / 146097; L = L - (146097 * N + 3) / 4; int256 _year = (4000 * (L + 1)) / 1461001; L = L - (1461 * _year) / 4 + 31; int256 _month = (80 * L) / 2447; int256 _day = L - (2447 * _month) / 80; L = _month / 11; _month = _month + 2 - 12 * L; _year = 100 * (N - 49) + _year + L; year = uint256(_year); month = uint256(_month); day = uint256(_day); } /// @dev Writes a prefix and an timestamp encoding to an output storage location /// This function is designed to only work with ASCII encoded strings. No emojis please. /// @param _prefix The string to write before the timestamp /// @param _timestamp the timestamp to encode and store /// @param _output the storage location of the output string /// NOTE - Current cost ~90k if gas is problem revisit and use assembly to remove the extra /// sstore s. function encodeAndWriteTimestamp( string memory _prefix, uint256 _timestamp, string storage _output ) external { _encodeAndWriteTimestamp(_prefix, _timestamp, _output); } /// @dev Sn internal version of the above function 'encodeAndWriteTimestamp' // solhint-disable-next-line function _encodeAndWriteTimestamp( string memory _prefix, uint256 _timestamp, string storage _output ) internal { // Cast the prefix string to a byte array bytes memory bytePrefix = bytes(_prefix); // Cast the output string to a byte array bytes storage bytesOutput = bytes(_output); // Copy the bytes from the prefix onto the byte array // NOTE - IF PREFIX CONTAINS NON-ASCII CHARS THIS WILL CAUSE AN INCORRECT STRING LENGTH for (uint256 i = 0; i < bytePrefix.length; i++) { bytesOutput.push(bytePrefix[i]); } // Add a '-' to the string to separate the prefix from the the date bytesOutput.push(bytes1("-")); // Add the date string timestampToDateString(_timestamp, _output); } /// @dev Converts a unix second encoded timestamp to a date format (year, month, day) /// then writes the string encoding of that to the output pointer. /// @param _timestamp the unix seconds timestamp /// @param _outputPointer the storage pointer to change. function timestampToDateString( uint256 _timestamp, string storage _outputPointer ) public { _timestampToDateString(_timestamp, _outputPointer); } /// @dev Sn internal version of the above function 'timestampToDateString' // solhint-disable-next-line function _timestampToDateString( uint256 _timestamp, string storage _outputPointer ) internal { // We pretend the string is a 'bytes' only push UTF8 encodings to it bytes storage output = bytes(_outputPointer); // First we get the day month and year (uint256 year, uint256 month, uint256 day) = _daysToDate( _timestamp / SECONDS_PER_DAY ); // First we add encoded day to the string { // Round out the second digit uint256 firstDigit = day / 10; // add it to the encoded byte for '0' output.push(bytes1(uint8(bytes1("0")) + uint8(firstDigit))); // Extract the second digit uint256 secondDigit = day % 10; // add it to the string output.push(bytes1(uint8(bytes1("0")) + uint8(secondDigit))); } // Next we encode the month string and add it if (month == 1) { stringPush(output, "J", "A", "N"); } else if (month == 2) { stringPush(output, "F", "E", "B"); } else if (month == 3) { stringPush(output, "M", "A", "R"); } else if (month == 4) { stringPush(output, "A", "P", "R"); } else if (month == 5) { stringPush(output, "M", "A", "Y"); } else if (month == 6) { stringPush(output, "J", "U", "N"); } else if (month == 7) { stringPush(output, "J", "U", "L"); } else if (month == 8) { stringPush(output, "A", "U", "G"); } else if (month == 9) { stringPush(output, "S", "E", "P"); } else if (month == 10) { stringPush(output, "O", "C", "T"); } else if (month == 11) { stringPush(output, "N", "O", "V"); } else if (month == 12) { stringPush(output, "D", "E", "C"); } else { revert("date decoding error"); } // We take the last two digits of the year // Hopefully that's enough { uint256 lastDigits = year % 100; // Round out the second digit uint256 firstDigit = lastDigits / 10; // add it to the encoded byte for '0' output.push(bytes1(uint8(bytes1("0")) + uint8(firstDigit))); // Extract the second digit uint256 secondDigit = lastDigits % 10; // add it to the string output.push(bytes1(uint8(bytes1("0")) + uint8(secondDigit))); } } function stringPush( bytes storage output, bytes1 data1, bytes1 data2, bytes1 data3 ) internal { output.push(data1); output.push(data2); output.push(data3); } }
// Forked from openzepplin // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit is IERC20 { /** * @dev Sets `value` as the allowance of `spender` over `owner`'s tokens, * given `owner`'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import "./libraries/ERC20Permit.sol"; import "./libraries/DateString.sol"; import "./interfaces/IInterestToken.sol"; import "./interfaces/ITranche.sol"; contract InterestToken is ERC20Permit, IInterestToken { // The tranche address which controls the minting ITranche public immutable tranche; /// @dev Initializes the ERC20 and writes the correct names /// @param _tranche The tranche contract address /// @param _strategySymbol The symbol of the associated WrappedPosition contract /// @param _timestamp The unlock time on the tranche /// @param _decimals The decimal encoding for this token constructor( address _tranche, string memory _strategySymbol, uint256 _timestamp, uint8 _decimals ) ERC20Permit( _processName("Element Yield Token ", _strategySymbol, _timestamp), _processSymbol("eY", _strategySymbol, _timestamp) ) { tranche = ITranche(_tranche); _setupDecimals(_decimals); } /// @notice We use this function to add the date to the name string /// @param _name start of the name /// @param _strategySymbol the strategy symbol /// @param _timestamp the unix second timestamp to be encoded and added to the end of the string function _processName( string memory _name, string memory _strategySymbol, uint256 _timestamp ) internal returns (string memory) { // Set the name in the super name = _name; // Use the library to write the rest DateString._encodeAndWriteTimestamp(_strategySymbol, _timestamp, name); // load and return the name return name; } /// @notice We use this function to add the date to the name string /// @param _symbol start of the symbol /// @param _strategySymbol the strategy symbol /// @param _timestamp the unix second timestamp to be encoded and added to the end of the string function _processSymbol( string memory _symbol, string memory _strategySymbol, uint256 _timestamp ) internal returns (string memory) { // Set the symbol in the super symbol = _symbol; // Use the library to write the rest DateString._encodeAndWriteTimestamp( _strategySymbol, _timestamp, symbol ); // load and return the name return symbol; } /// @dev Aliasing of the lookup method for the supply of yield tokens which /// improves our ERC20 compatibility. /// @return The total supply of yield tokens function totalSupply() external view returns (uint256) { return uint256(tranche.interestSupply()); } /// @dev Prevents execution if the caller isn't the tranche modifier onlyMintAuthority() { require( msg.sender == address(tranche), "caller is not an authorized minter" ); _; } /// @dev Mints tokens to an address /// @param _account The account to mint to /// @param _amount The amount to mint function mint(address _account, uint256 _amount) external override onlyMintAuthority { _mint(_account, _amount); } /// @dev Burns tokens from an address /// @param _account The account to burn from /// @param _amount The amount of token to burn function burn(address _account, uint256 _amount) external override onlyMintAuthority { _burn(_account, _amount); } }
{ "optimizer": { "enabled": true, "runs": 7500 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SpeedBumpHit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hitSpeedbump","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestSupply","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestToken","outputs":[{"internalType":"contract IInterestToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"position","outputs":[{"internalType":"contract IWrappedPosition","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"}],"name":"prefundedDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"speedbump","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"valueSupplied","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"withdrawInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"withdrawPrincipal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604080518082018252601881527f456c656d656e74205072696e636970616c20546f6b656e200000000000000000602080830191825283518085019094526002845261065560f41b90840152815191929162000072916000916200063e565b508051620000889060019060208401906200063e565b506002805460ff1916601217905560036020526000197f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff8190553060009081526040902055620000d762000384565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600060405162000109919062000854565b60408051918290038220828201825260018352603160f81b60209384015290516200015c93927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6914691309101620008f9565b6040516020818303038152906040528051906020012060068190555050506000339050600080600080846001600160a01b0316633bc5de306040518163ffffffff1660e01b8152600401608060405180830381600087803b158015620001c157600080fd5b505af1158015620001d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fc9190620006e4565b6001600160601b0319606083811b821660805285901b1660a05261010083905260408051637e062a3560e11b81529051949850929650909450925085916000916001600160a01b0384169163fc0c546a91600480820192602092909190829003018186803b1580156200026e57600080fd5b505afa15801562000283573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002a991906200073f565b9050806001600160a01b031660c0816001600160a01b031660601b815250506000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156200030457600080fd5b505afa15801562000319573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200033f919062000813565b7fff0000000000000000000000000000000000000000000000000000000000000060f882901b1660e0529050620003768162000628565b505050505050505062000a14565b6000339050600080600080846001600160a01b0316633bc5de306040518163ffffffff1660e01b8152600401608060405180830381600087803b158015620003cb57600080fd5b505af1158015620003e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004069190620006e4565b93509350935093506000846001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156200044a57600080fd5b505afa1580156200045f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000489919081019062000765565b60405190915060009060019082906001600160a01b03861690637a0674a360e11b90620004bf9087908b90869060240162000925565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004ff919062000836565b600060405180830381855af49150503d80600081146200053c576040519150601f19603f3d011682016040523d82523d6000602084013e62000541565b606091505b505090506000856001600160a01b031663f40ce94660e01b868a86604051602401620005709392919062000925565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005b0919062000836565b600060405180830381855af49150503d8060008114620005ed576040519150601f19603f3d011682016040523d82523d6000602084013e620005f2565b606091505b50509050818015620006015750805b6200061c57634e487b7160e01b600052600160045260246000fd5b50505050505050505050565b6002805460ff191660ff92909216919091179055565b8280546200064c90620009a8565b90600052602060002090601f016020900481019282620006705760008555620006bb565b82601f106200068b57805160ff1916838001178555620006bb565b82800160010185558215620006bb579182015b82811115620006bb5782518255916020019190600101906200069e565b50620006c9929150620006cd565b5090565b5b80821115620006c95760008155600101620006ce565b60008060008060808587031215620006fa578384fd5b84516200070781620009fb565b6020860151604087015191955093506200072181620009fb565b60608601519092506200073481620009fb565b939692955090935050565b60006020828403121562000751578081fd5b81516200075e81620009fb565b9392505050565b60006020828403121562000777578081fd5b81516001600160401b03808211156200078e578283fd5b818401915084601f830112620007a2578283fd5b815181811115620007b757620007b7620009e5565b604051601f8201601f191681016020018381118282101715620007de57620007de620009e5565b604052818152838201602001871015620007f6578485fd5b6200080982602083016020870162000975565b9695505050505050565b60006020828403121562000825578081fd5b815160ff811681146200075e578182fd5b600082516200084a81846020870162000975565b9190910192915050565b81546000908190600281046001808316806200087157607f831692505b60208084108214156200089257634e487b7160e01b87526022600452602487fd5b818015620008a95760018114620008bb57620008eb565b60ff19861689528489019650620008eb565b620008c68a62000969565b885b86811015620008e35781548b820152908501908301620008c8565b505084890196505b509498975050505050505050565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b60006060825284518060608401526200094681608085016020890162000975565b60208301949094525060408101919091526080601f909201601f19160101919050565b60009081526020902090565b60005b838110156200099257818101518382015260200162000978565b83811115620009a2576000848401525b50505050565b600281046001821680620009bd57607f821691505b60208210811415620009df57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462000a1157600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160f81c610100516120b862000acb600039600081816104a901528181610ba501528181610d3901528181611017015261143d01526000505060008181610a470152610b2b01526000818161040c015281816105d50152818161076e01528181610a8401528181610c2301528181610d7d015281816110b50152818161120801526112da01526000818161052d01528181610b610152610f9101526120b86000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80636e553f65116100ee57806385f45c8811610097578063a9059cbb11610071578063a9059cbb1461030f578063aa082a9d14610322578063d505accf1461032a578063dd62ed3e1461033d576101a3565b806385f45c88146102e1578063884e17f3146102f457806395d89b4114610307576101a3565b8063764b666c116100c8578063764b666c146102bc5780637da081a2146102c45780637ecebe00146102ce576101a3565b80636e553f65146102805780636f307dc3146102a157806370a08231146102a9576101a3565b806323b872dd116101505780633644e5151161012a5780633644e51514610268578063421b15c11461027057806363cf7cdd14610278576101a3565b806323b872dd1461023857806330adf81f1461024b578063313ce56714610253576101a3565b8063095ea7b311610181578063095ea7b3146101f05780631210aac21461021057806318160ddd14610230576101a3565b8063041be7c2146101a857806306fdde03146101c657806309218e91146101db575b600080fd5b6101b0610350565b6040516101bd9190611eb7565b60405180910390f35b6101ce61037c565b6040516101bd9190611b8c565b6101e361040a565b6040516101bd9190611a73565b6102036101fe36600461196a565b61042e565b6040516101bd9190611b19565b61022361021e3660046119cb565b6104a5565b6040516101bd9190611b24565b610223610807565b6102036102463660046118be565b61081f565b6102236109f1565b61025b610a15565b6040516101bd9190611ee2565b610223610a1e565b610223610a24565b6101b0610a2a565b61029361028e3660046119cb565b610a42565b6040516101bd929190611ed4565b6101e3610b29565b6102236102b7366004611872565b610b4d565b6101e3610b5f565b6102cc610b83565b005b6102236102dc366004611872565b610d22565b6102936102ef366004611872565b610d34565b6102236103023660046119cb565b611013565b6101ce61141a565b61020361031d36600461196a565b611427565b61022361143b565b6102cc6103383660046118f9565b61145f565b61022361034b36600461188c565b611709565b60075470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6000805461038990611fc6565b80601f01602080910402602001604051908101604052809291908181526020018280546103b590611fc6565b80156104025780601f106103d757610100808354040283529160200191610402565b820191906000526020600020905b8154815290600101906020018083116103e557829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610494908690611b24565b60405180910390a350600192915050565b60007f00000000000000000000000000000000000000000000000000000000000000004210156104f05760405162461bcd60e51b81526004016104e790611d36565b60405180910390fd5b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906105649033908790600401611ac5565b600060405180830381600087803b15801561057e57600080fd5b505af1158015610592573d6000803e3d6000fd5b50506040517f3af9e6690000000000000000000000000000000000000000000000000000000081526000925073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169150633af9e6699061060b903090600401611a73565b60206040518083038186803b15801561062357600080fd5b505afa158015610637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065b91906119b3565b6007549091506fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416600082841161069b5760006106a5565b6106a58385611faf565b90506000826106b48984611f41565b6106be9190611f08565b90506000670de0b6b3a76400006106db6509184e72a00084611f41565b6106e59190611f08565b6106ef9083611faf565b90506106fb8985611faf565b600780546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790556040517f67caf87100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906367caf871906107a7908c9087908790600401611aeb565b6040805180830381600087803b1580156107c057600080fd5b505af11580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f891906119ed565b509a9950505050505050505050565b6007546fffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054828110156108655760405162461bcd60e51b81526004016104e790611e80565b73ffffffffffffffffffffffffffffffffffffffff851633146109385773ffffffffffffffffffffffffffffffffffffffff851660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461093657838110156108fa5760405162461bcd60e51b81526004016104e790611bfd565b6109048482611faf565b73ffffffffffffffffffffffffffffffffffffffff871660009081526004602090815260408083203384529091529020555b505b6109428382611faf565b73ffffffffffffffffffffffffffffffffffffffff808716600090815260036020526040808220939093559086168152205461097f908490611ef0565b73ffffffffffffffffffffffffffffffffffffffff80861660008181526003602052604090819020939093559151908716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109de908790611b24565b60405180910390a3506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b60065481565b60085481565b6007546fffffffffffffffffffffffffffffffff1681565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166323b872dd337f0000000000000000000000000000000000000000000000000000000000000000876040518463ffffffff1660e01b8152600401610ac293929190611a94565b602060405180830381600087803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b149190611993565b50610b1e83610d34565b915091509250929050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60036020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60085415610ba35760405162461bcd60e51b81526004016104e790611da4565b7f0000000000000000000000000000000000000000000000000000000000000000421015610be35760405162461bcd60e51b81526004016104e790611d36565b6040517f3af9e66900000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633af9e66990610c58903090600401611a73565b60206040518083038186803b158015610c7057600080fd5b505afa158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca891906119b3565b6007549091506fffffffffffffffffffffffffffffffff16811015610d07577ff7f87880c827db1e5aaa7a648e710c6e9c3a608de27471889dbd94199232c31f42604051610cf69190611b24565b60405180910390a142600855610d1f565b60405162461bcd60e51b81526004016104e790611e49565b50565b60056020526000908152604090205481565b6000807f00000000000000000000000000000000000000000000000000000000000000004210610d765760405162461bcd60e51b81526004016104e790611cff565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166385f45c88306040518263ffffffff1660e01b8152600401610dd49190611a73565b606060405180830381600087803b158015610dee57600080fd5b505af1158015610e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e269190611a10565b91945092509050600083610e3a8484611f41565b610e449190611f08565b6007549091506fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416610e7f836002611ef0565b821115610e9e5760405162461bcd60e51b81526004016104e790611e12565b60008083118015610eae57508284115b15610ee4578186610ebf8587611faf565b610ec99190611f41565b610ed39190611f08565b610edd9087611faf565b9050610ee7565b50845b610ef18184611ef0565b610efb8784611ef0565b600780546fffffffffffffffffffffffffffffffff938416928416700100000000000000000000000000000000029316929092177fffffffffffffffffffffffffffffffff00000000000000000000000000000000161790556040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990610fc8908d908a90600401611ac5565b600060405180830381600087803b158015610fe257600080fd5b505af1158015610ff6573d6000803e3d6000fd5b505050506110048a82611726565b97509395505050505050915091565b60007f00000000000000000000000000000000000000000000000000000000000000004210156110555760405162461bcd60e51b81526004016104e790611d36565b60085460075484906fffffffffffffffffffffffffffffffff168215611188576040517f3af9e66900000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633af9e669906110ea903090600401611a73565b60206040518083038186803b15801561110257600080fd5b505afa158015611116573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113a91906119b3565b905081811015611186578161114f8289611f41565b6111599190611f08565b9250426111696202a30086611ef0565b106111865760405162461bcd60e51b81526004016104e790611c34565b505b61119233876117bf565b61119c8682611f7e565b600780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790556040517f70a082310000000000000000000000000000000000000000000000000000000081526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190611252903090600401611a73565b60206040518083038186803b15801561126a57600080fd5b505afa15801561127e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a291906119b3565b90506000670de0b6b3a76400006112bf6509184e72a00086611f41565b6112c99190611f08565b6112d39085611faf565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166367caf8718a88866040518463ffffffff1660e01b815260040161133593929190611aeb565b6040805180830381600087803b15801561134e57600080fd5b505af1158015611362573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138691906119ed565b90925090506000816113988487611f41565b6113a29190611f08565b90508581101561140b57876113c95760405162461bcd60e51b81526004016104e790611e12565b426113d76202a3008a611ef0565b1061140b577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b50909998505050505050505050565b6001805461038990611fc6565b600061143433848461081f565b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60065473ffffffffffffffffffffffffffffffffffffffff881660009081526005602090815260408083205490519293926114c5927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611b2d565b604051602081830303815290604052805190602001206040516020016114ec929190611a3d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120905073ffffffffffffffffffffffffffffffffffffffff88166115575760405162461bcd60e51b81526004016104e790611cc8565b6001818585856040516000815260200160405260405161157a9493929190611b6e565b6020604051602081039080840390855afa15801561159c573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146115f05760405162461bcd60e51b81526004016104e790611d6d565b8415806115fd5750844211155b6116195760405162461bcd60e51b81526004016104e790611ddb565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116595760405162461bcd60e51b81526004016104e790611c6b565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260056020526040812080549161168a8361201a565b909155505073ffffffffffffffffffffffffffffffffffffffff8089166000818152600460209081526040808320948c168084529490915290819020899055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906116f7908a90611b24565b60405180910390a35050505050505050565b600460209081526000928352604080842090915290825290205481565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902054611757908290611ef0565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906117b3908590611b24565b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020546117f0908290611faf565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600360205260408082209390935591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906117b3908590611b24565b803573ffffffffffffffffffffffffffffffffffffffff8116811461186d57600080fd5b919050565b600060208284031215611883578081fd5b61143482611849565b6000806040838503121561189e578081fd5b6118a783611849565b91506118b560208401611849565b90509250929050565b6000806000606084860312156118d2578081fd5b6118db84611849565b92506118e960208501611849565b9150604084013590509250925092565b600080600080600080600060e0888a031215611913578283fd5b61191c88611849565b965061192a60208901611849565b95506040880135945060608801359350608088013560ff8116811461194d578384fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561197c578182fd5b61198583611849565b946020939093013593505050565b6000602082840312156119a4578081fd5b81518015158114611434578182fd5b6000602082840312156119c4578081fd5b5051919050565b600080604083850312156119dd578182fd5b823591506118b560208401611849565b600080604083850312156119ff578182fd5b505080516020909101519092909150565b600080600060608486031215611a24578283fd5b8351925060208401519150604084015190509250925092565b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b95865273ffffffffffffffffffffffffffffffffffffffff94851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611bb857858101830151858201604001528201611b9c565b81811115611bc95783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6020808252601d908201527f45524332303a20696e73756666696369656e742d616c6c6f77616e6365000000604082015260600190565b60208082526007908201527f453a4561726c7900000000000000000000000000000000000000000000000000604082015260600190565b60208082526022908201527f45524332303a20696e76616c6964207369676e6174757265202773272076616c60408201527f7565000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526018908201527f45524332303a20696e76616c69642d616464726573732d300000000000000000604082015260600190565b60208082526007908201527f6578706972656400000000000000000000000000000000000000000000000000604082015260600190565b6020808252600d908201527f453a4e6f74204578706972656400000000000000000000000000000000000000604082015260600190565b60208082526015908201527f45524332303a20696e76616c69642d7065726d69740000000000000000000000604082015260600190565b6020808252600c908201527f453a416c72656164795365740000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f45524332303a207065726d69742d657870697265640000000000000000000000604082015260600190565b60208082526009908201527f453a4e45475f494e540000000000000000000000000000000000000000000000604082015260600190565b60208082526008908201527f453a4e6f4c6f7373000000000000000000000000000000000000000000000000604082015260600190565b6020808252601b908201527f45524332303a20696e73756666696369656e742d62616c616e63650000000000604082015260600190565b6fffffffffffffffffffffffffffffffff91909116815260200190565b918252602082015260400190565b60ff91909116815260200190565b60008219821115611f0357611f03612053565b500190565b600082611f3c577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611f7957611f79612053565b500290565b60006fffffffffffffffffffffffffffffffff83811690831681811015611fa757611fa7612053565b039392505050565b600082821015611fc157611fc1612053565b500390565b600281046001821680611fda57607f821691505b60208210811415612014577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561204c5761204c612053565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea2646970667358221220a18927d943c0e2e2c7f08df5931c0832a5480b54215a2272df132f2dd78427d064736f6c63430008000033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101a35760003560e01c80636e553f65116100ee57806385f45c8811610097578063a9059cbb11610071578063a9059cbb1461030f578063aa082a9d14610322578063d505accf1461032a578063dd62ed3e1461033d576101a3565b806385f45c88146102e1578063884e17f3146102f457806395d89b4114610307576101a3565b8063764b666c116100c8578063764b666c146102bc5780637da081a2146102c45780637ecebe00146102ce576101a3565b80636e553f65146102805780636f307dc3146102a157806370a08231146102a9576101a3565b806323b872dd116101505780633644e5151161012a5780633644e51514610268578063421b15c11461027057806363cf7cdd14610278576101a3565b806323b872dd1461023857806330adf81f1461024b578063313ce56714610253576101a3565b8063095ea7b311610181578063095ea7b3146101f05780631210aac21461021057806318160ddd14610230576101a3565b8063041be7c2146101a857806306fdde03146101c657806309218e91146101db575b600080fd5b6101b0610350565b6040516101bd9190611eb7565b60405180910390f35b6101ce61037c565b6040516101bd9190611b8c565b6101e361040a565b6040516101bd9190611a73565b6102036101fe36600461196a565b61042e565b6040516101bd9190611b19565b61022361021e3660046119cb565b6104a5565b6040516101bd9190611b24565b610223610807565b6102036102463660046118be565b61081f565b6102236109f1565b61025b610a15565b6040516101bd9190611ee2565b610223610a1e565b610223610a24565b6101b0610a2a565b61029361028e3660046119cb565b610a42565b6040516101bd929190611ed4565b6101e3610b29565b6102236102b7366004611872565b610b4d565b6101e3610b5f565b6102cc610b83565b005b6102236102dc366004611872565b610d22565b6102936102ef366004611872565b610d34565b6102236103023660046119cb565b611013565b6101ce61141a565b61020361031d36600461196a565b611427565b61022361143b565b6102cc6103383660046118f9565b61145f565b61022361034b36600461188c565b611709565b60075470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6000805461038990611fc6565b80601f01602080910402602001604051908101604052809291908181526020018280546103b590611fc6565b80156104025780601f106103d757610100808354040283529160200191610402565b820191906000526020600020905b8154815290600101906020018083116103e557829003601f168201915b505050505081565b7f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610494908690611b24565b60405180910390a350600192915050565b60007f0000000000000000000000000000000000000000000000000000000061f406cc4210156104f05760405162461bcd60e51b81526004016104e790611d36565b60405180910390fd5b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f1294e805b992320a3515682c6ab0fe6251067e51690639dc29fac906105649033908790600401611ac5565b600060405180830381600087803b15801561057e57600080fd5b505af1158015610592573d6000803e3d6000fd5b50506040517f3af9e6690000000000000000000000000000000000000000000000000000000081526000925073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b0169150633af9e6699061060b903090600401611a73565b60206040518083038186803b15801561062357600080fd5b505afa158015610637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065b91906119b3565b6007549091506fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416600082841161069b5760006106a5565b6106a58385611faf565b90506000826106b48984611f41565b6106be9190611f08565b90506000670de0b6b3a76400006106db6509184e72a00084611f41565b6106e59190611f08565b6106ef9083611faf565b90506106fb8985611faf565b600780546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000292169190911790556040517f67caf87100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b016906367caf871906107a7908c9087908790600401611aeb565b6040805180830381600087803b1580156107c057600080fd5b505af11580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f891906119ed565b509a9950505050505050505050565b6007546fffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054828110156108655760405162461bcd60e51b81526004016104e790611e80565b73ffffffffffffffffffffffffffffffffffffffff851633146109385773ffffffffffffffffffffffffffffffffffffffff851660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461093657838110156108fa5760405162461bcd60e51b81526004016104e790611bfd565b6109048482611faf565b73ffffffffffffffffffffffffffffffffffffffff871660009081526004602090815260408083203384529091529020555b505b6109428382611faf565b73ffffffffffffffffffffffffffffffffffffffff808716600090815260036020526040808220939093559086168152205461097f908490611ef0565b73ffffffffffffffffffffffffffffffffffffffff80861660008181526003602052604090819020939093559151908716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906109de908790611b24565b60405180910390a3506001949350505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025460ff1681565b60065481565b60085481565b6007546fffffffffffffffffffffffffffffffff1681565b6000807f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4873ffffffffffffffffffffffffffffffffffffffff166323b872dd337f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b0876040518463ffffffff1660e01b8152600401610ac293929190611a94565b602060405180830381600087803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b149190611993565b50610b1e83610d34565b915091509250929050565b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b60036020526000908152604090205481565b7f000000000000000000000000f1294e805b992320a3515682c6ab0fe6251067e581565b60085415610ba35760405162461bcd60e51b81526004016104e790611da4565b7f0000000000000000000000000000000000000000000000000000000061f406cc421015610be35760405162461bcd60e51b81526004016104e790611d36565b6040517f3af9e66900000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b01690633af9e66990610c58903090600401611a73565b60206040518083038186803b158015610c7057600080fd5b505afa158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca891906119b3565b6007549091506fffffffffffffffffffffffffffffffff16811015610d07577ff7f87880c827db1e5aaa7a648e710c6e9c3a608de27471889dbd94199232c31f42604051610cf69190611b24565b60405180910390a142600855610d1f565b60405162461bcd60e51b81526004016104e790611e49565b50565b60056020526000908152604090205481565b6000807f0000000000000000000000000000000000000000000000000000000061f406cc4210610d765760405162461bcd60e51b81526004016104e790611cff565b60008060007f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b073ffffffffffffffffffffffffffffffffffffffff166385f45c88306040518263ffffffff1660e01b8152600401610dd49190611a73565b606060405180830381600087803b158015610dee57600080fd5b505af1158015610e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e269190611a10565b91945092509050600083610e3a8484611f41565b610e449190611f08565b6007549091506fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416610e7f836002611ef0565b821115610e9e5760405162461bcd60e51b81526004016104e790611e12565b60008083118015610eae57508284115b15610ee4578186610ebf8587611faf565b610ec99190611f41565b610ed39190611f08565b610edd9087611faf565b9050610ee7565b50845b610ef18184611ef0565b610efb8784611ef0565b600780546fffffffffffffffffffffffffffffffff938416928416700100000000000000000000000000000000029316929092177fffffffffffffffffffffffffffffffff00000000000000000000000000000000161790556040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f1294e805b992320a3515682c6ab0fe6251067e516906340c10f1990610fc8908d908a90600401611ac5565b600060405180830381600087803b158015610fe257600080fd5b505af1158015610ff6573d6000803e3d6000fd5b505050506110048a82611726565b97509395505050505050915091565b60007f0000000000000000000000000000000000000000000000000000000061f406cc4210156110555760405162461bcd60e51b81526004016104e790611d36565b60085460075484906fffffffffffffffffffffffffffffffff168215611188576040517f3af9e66900000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b01690633af9e669906110ea903090600401611a73565b60206040518083038186803b15801561110257600080fd5b505afa158015611116573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113a91906119b3565b905081811015611186578161114f8289611f41565b6111599190611f08565b9250426111696202a30086611ef0565b106111865760405162461bcd60e51b81526004016104e790611c34565b505b61119233876117bf565b61119c8682611f7e565b600780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790556040517f70a082310000000000000000000000000000000000000000000000000000000081526000907f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b073ffffffffffffffffffffffffffffffffffffffff16906370a0823190611252903090600401611a73565b60206040518083038186803b15801561126a57600080fd5b505afa15801561127e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a291906119b3565b90506000670de0b6b3a76400006112bf6509184e72a00086611f41565b6112c99190611f08565b6112d39085611faf565b90506000807f000000000000000000000000dea04ffc66ecd7bf35782c70255852b34102c3b073ffffffffffffffffffffffffffffffffffffffff166367caf8718a88866040518463ffffffff1660e01b815260040161133593929190611aeb565b6040805180830381600087803b15801561134e57600080fd5b505af1158015611362573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138691906119ed565b90925090506000816113988487611f41565b6113a29190611f08565b90508581101561140b57876113c95760405162461bcd60e51b81526004016104e790611e12565b426113d76202a3008a611ef0565b1061140b577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b50909998505050505050505050565b6001805461038990611fc6565b600061143433848461081f565b9392505050565b7f0000000000000000000000000000000000000000000000000000000061f406cc81565b60065473ffffffffffffffffffffffffffffffffffffffff881660009081526005602090815260408083205490519293926114c5927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611b2d565b604051602081830303815290604052805190602001206040516020016114ec929190611a3d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120905073ffffffffffffffffffffffffffffffffffffffff88166115575760405162461bcd60e51b81526004016104e790611cc8565b6001818585856040516000815260200160405260405161157a9493929190611b6e565b6020604051602081039080840390855afa15801561159c573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146115f05760405162461bcd60e51b81526004016104e790611d6d565b8415806115fd5750844211155b6116195760405162461bcd60e51b81526004016104e790611ddb565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156116595760405162461bcd60e51b81526004016104e790611c6b565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260056020526040812080549161168a8361201a565b909155505073ffffffffffffffffffffffffffffffffffffffff8089166000818152600460209081526040808320948c168084529490915290819020899055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906116f7908a90611b24565b60405180910390a35050505050505050565b600460209081526000928352604080842090915290825290205481565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040902054611757908290611ef0565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600360205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906117b3908590611b24565b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020546117f0908290611faf565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600360205260408082209390935591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906117b3908590611b24565b803573ffffffffffffffffffffffffffffffffffffffff8116811461186d57600080fd5b919050565b600060208284031215611883578081fd5b61143482611849565b6000806040838503121561189e578081fd5b6118a783611849565b91506118b560208401611849565b90509250929050565b6000806000606084860312156118d2578081fd5b6118db84611849565b92506118e960208501611849565b9150604084013590509250925092565b600080600080600080600060e0888a031215611913578283fd5b61191c88611849565b965061192a60208901611849565b95506040880135945060608801359350608088013560ff8116811461194d578384fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561197c578182fd5b61198583611849565b946020939093013593505050565b6000602082840312156119a4578081fd5b81518015158114611434578182fd5b6000602082840312156119c4578081fd5b5051919050565b600080604083850312156119dd578182fd5b823591506118b560208401611849565b600080604083850312156119ff578182fd5b505080516020909101519092909150565b600080600060608486031215611a24578283fd5b8351925060208401519150604084015190509250925092565b7f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9390931683526020830191909152604082015260600190565b901515815260200190565b90815260200190565b95865273ffffffffffffffffffffffffffffffffffffffff94851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611bb857858101830151858201604001528201611b9c565b81811115611bc95783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6020808252601d908201527f45524332303a20696e73756666696369656e742d616c6c6f77616e6365000000604082015260600190565b60208082526007908201527f453a4561726c7900000000000000000000000000000000000000000000000000604082015260600190565b60208082526022908201527f45524332303a20696e76616c6964207369676e6174757265202773272076616c60408201527f7565000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526018908201527f45524332303a20696e76616c69642d616464726573732d300000000000000000604082015260600190565b60208082526007908201527f6578706972656400000000000000000000000000000000000000000000000000604082015260600190565b6020808252600d908201527f453a4e6f74204578706972656400000000000000000000000000000000000000604082015260600190565b60208082526015908201527f45524332303a20696e76616c69642d7065726d69740000000000000000000000604082015260600190565b6020808252600c908201527f453a416c72656164795365740000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f45524332303a207065726d69742d657870697265640000000000000000000000604082015260600190565b60208082526009908201527f453a4e45475f494e540000000000000000000000000000000000000000000000604082015260600190565b60208082526008908201527f453a4e6f4c6f7373000000000000000000000000000000000000000000000000604082015260600190565b6020808252601b908201527f45524332303a20696e73756666696369656e742d62616c616e63650000000000604082015260600190565b6fffffffffffffffffffffffffffffffff91909116815260200190565b918252602082015260400190565b60ff91909116815260200190565b60008219821115611f0357611f03612053565b500190565b600082611f3c577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611f7957611f79612053565b500290565b60006fffffffffffffffffffffffffffffffff83811690831681811015611fa757611fa7612053565b039392505050565b600082821015611fc157611fc1612053565b500390565b600281046001821680611fda57607f821691505b60208210811415612014577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561204c5761204c612053565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea2646970667358221220a18927d943c0e2e2c7f08df5931c0832a5480b54215a2272df132f2dd78427d064736f6c63430008000033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.