Source Code
Latest 25 from a total of 1,878 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem | 1417991 | 1461 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1401587 | 1463 days ago | IN | 0 MOVR | 0.00002118 | ||||
| Redeem | 1317444 | 1476 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1308889 | 1477 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1296367 | 1479 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1279038 | 1481 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1278420 | 1482 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1277477 | 1482 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1276159 | 1482 days ago | IN | 0 MOVR | 0.00003078 | ||||
| Redeem | 1275093 | 1482 days ago | IN | 0 MOVR | 0.00003078 | ||||
| Redeem | 1274795 | 1482 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1274487 | 1482 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1273339 | 1482 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1272908 | 1482 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1272170 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1271656 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1271428 | 1483 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1270832 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1270694 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1270329 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1269601 | 1483 days ago | IN | 0 MOVR | 0.00012905 | ||||
| Redeem | 1269188 | 1483 days ago | IN | 0 MOVR | 0.00003078 | ||||
| Redeem | 1269055 | 1483 days ago | IN | 0 MOVR | 0.00011945 | ||||
| Redeem | 1268693 | 1483 days ago | IN | 0 MOVR | 0.00012434 | ||||
| Redeem | 1268675 | 1483 days ago | IN | 0 MOVR | 0.00012434 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MOVRBondDepository
Compiler Version
v0.7.5+commit.eb77ed08
Optimization Enabled:
Yes with 9999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "../types/Policy.sol";
import "../types/ERC20Permit.sol";
import "../libraries/SafeERC20.sol";
import "../libraries/FixedPoint.sol";
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
interface ITreasury {
function deposit( uint _amount, address _token, uint _profit ) external returns ( bool );
function valueOf( address _token, uint _amount ) external view returns ( uint value_ );
function mintRewards( address _recipient, uint _amount ) external;
}
interface IBondCalculator {
function valuation( address _LP, uint _amount ) external view returns ( uint );
function markdown( address _LP ) external view returns ( uint );
}
interface IStaking {
function stake( uint _amount, address _recipient ) external returns ( bool );
}
interface IStakingHelper {
function stake( uint _amount, address _recipient ) external;
}
contract MOVRBondDepository is Policy {
using FixedPoint for *;
using SafeERC20 for IERC20;
using SafeMath for uint;
/* ======== EVENTS ======== */
event BondCreated( uint deposit, uint indexed payout, uint indexed expires, uint indexed priceInUSD );
event BondRedeemed( address indexed recipient, uint payout, uint remaining );
event BondPriceChanged( uint indexed priceInUSD, uint indexed internalPrice, uint indexed debtRatio );
event ControlVariableAdjustment( uint initialBCV, uint newBCV, uint adjustment, bool addition );
/* ======== STATE VARIABLES ======== */
address public immutable ROME; // token given as payment for bond
address public immutable principle; // token used to create bond
address public immutable treasury; // mints ROME when receives principle
address public immutable DAO; // receives fee share from bond
address public immutable bondCalculator; // calculates value of LP tokens
AggregatorV3Interface internal priceFeed;
address public staking; // to auto-stake payout
address public stakingHelper; // to stake and claim if no staking warmup
bool public useHelper;
Terms public terms; // stores terms for new bonds
Adjust public adjustment; // stores adjustment to BCV data
mapping( address => Bond ) public bondInfo; // stores bond information for depositors
uint public totalDebt; // total value of outstanding bonds; used for pricing
uint public lastDecay; // reference block for debt decay
/* ======== STRUCTS ======== */
// Info for creating new bonds
struct Terms {
uint controlVariable; // scaling variable for price
uint vestingTerm; // in blocks
uint minimumPrice; // vs principle value.
uint maxPayout; // in thousandths of a %. i.e. 500 = 0.5%
uint maxDebt; // 9 decimal debt ratio, max % total supply created as debt
}
// Info for bond holder
struct Bond {
uint payout; // ROME remaining to be paid
uint vesting; // Blocks left to vest
uint lastBlock; // Last interaction
uint pricePaid; // In DAI, for front end viewing
}
// Info for incremental adjustments to control variable
struct Adjust {
bool add; // addition or subtraction
uint rate; // increment
uint target; // BCV when adjustment finished
uint buffer; // minimum length (in blocks) between adjustments
uint lastBlock; // block when last adjustment made
}
/* ======== INITIALIZATION ======== */
constructor (
address _ROME,
address _principle,
address _treasury,
address _DAO,
address _bondCalculator,
address _feed
) {
require( _ROME != address(0) );
ROME = _ROME;
require( _principle != address(0) );
principle = _principle;
require( _treasury != address(0) );
treasury = _treasury;
require( _DAO != address(0) );
DAO = _DAO;
// bondCalculator should be address(0) if not LP bond
bondCalculator = _bondCalculator;
priceFeed = AggregatorV3Interface( _feed );
}
/**
* @notice initializes bond parameters
* @param _controlVariable uint
* @param _vestingTerm uint
* @param _minimumPrice uint
* @param _maxPayout uint
* @param _maxDebt uint
* @param _initialDebt uint
*/
function initializeBondTerms(
uint _controlVariable,
uint _vestingTerm,
uint _minimumPrice,
uint _maxPayout,
uint _maxDebt,
uint _initialDebt
) external onlyPolicy() {
require( terms.controlVariable == 0, "Bonds must be initialized from 0" );
terms = Terms ({
controlVariable: _controlVariable,
vestingTerm: _vestingTerm,
minimumPrice: _minimumPrice,
maxPayout: _maxPayout,
maxDebt: _maxDebt
});
totalDebt = _initialDebt;
lastDecay = block.number;
}
/* ======== POLICY FUNCTIONS ======== */
enum PARAMETER { VESTING, PAYOUT, DEBT }
/**
* @notice set parameters for new bonds
* @param _parameter PARAMETER
* @param _input uint
*/
function setBondTerms ( PARAMETER _parameter, uint _input ) external onlyPolicy() {
if ( _parameter == PARAMETER.VESTING ) { // 0
require( _input >= 10000, "Vesting must be longer than 36 hours" );
terms.vestingTerm = _input;
} else if ( _parameter == PARAMETER.PAYOUT ) { // 1
require( _input <= 1000, "Payout cannot be above 1 percent" );
terms.maxPayout = _input;
} else if ( _parameter == PARAMETER.DEBT ) { // 2
terms.maxDebt = _input;
}
}
/**
* @notice set control variable adjustment
* @param _addition bool
* @param _increment uint
* @param _target uint
* @param _buffer uint
*/
function setAdjustment (
bool _addition,
uint _increment,
uint _target,
uint _buffer
) external onlyPolicy() {
require( _increment <= terms.controlVariable.mul( 25 ).div( 1000 ) || _increment == 1, "Increment too large" );
adjustment = Adjust({
add: _addition,
rate: _increment,
target: _target,
buffer: _buffer,
lastBlock: block.number
});
}
/**
* @notice set contract for auto stake
* @param _staking address
* @param _helper bool
*/
function setStaking( address _staking, bool _helper ) external onlyPolicy() {
require( _staking != address(0) );
if ( _helper ) {
useHelper = true;
stakingHelper = _staking;
} else {
useHelper = false;
staking = _staking;
}
}
/* ======== USER FUNCTIONS ======== */
/**
* @notice deposit bond
* @param _amount uint
* @param _maxPrice uint
* @param _depositor address
* @return uint
*/
function deposit(
uint _amount,
uint _maxPrice,
address _depositor
) external returns ( uint ) {
require( _depositor != address(0), "Invalid address" );
decayDebt();
require( totalDebt <= terms.maxDebt && terms.maxDebt > 0, "Max capacity reached" );
uint priceInUSD = bondPriceInUSD(); // Stored in bond info
uint nativePrice = _bondPrice();
require( _maxPrice >= nativePrice, "Slippage limit: more than max price" ); // slippage protection
uint value = ITreasury( treasury ).valueOf( principle, _amount );
uint payout = payoutFor( value ); // payout to bonder is computed
require( payout >= 10000000, "Bond too small" ); // must be > 0.01 ROME ( underflow protection )
require( payout <= maxPayout(), "Bond too large"); // size protection because there is no slippage
/**
asset carries risk and is not minted against
asset transfered to treasury and rewards minted as payout
*/
IERC20( principle ).safeTransferFrom( msg.sender, treasury, _amount );
ITreasury( treasury ).mintRewards( address(this), payout );
// total debt is increased
totalDebt = totalDebt.add( value );
// depositor info is stored
bondInfo[ _depositor ] = Bond({
payout: bondInfo[ _depositor ].payout.add( payout ),
vesting: terms.vestingTerm,
lastBlock: block.number,
pricePaid: priceInUSD
});
// indexed events are emitted
emit BondCreated( _amount, payout, block.number.add( terms.vestingTerm ), priceInUSD );
emit BondPriceChanged( bondPriceInUSD(), _bondPrice(), debtRatio() );
adjust(); // control variable is adjusted
return payout;
}
/**
* @notice redeem bond for user
* @param _recipient address
* @param _stake bool
* @return uint
*/
function redeem( address _recipient, bool _stake ) external returns ( uint ) {
Bond memory info = bondInfo[ _recipient ];
uint percentVested = percentVestedFor( _recipient ); // (blocks since last interaction / vesting term remaining)
if ( percentVested >= 10000 ) { // if fully vested
delete bondInfo[ _recipient ]; // delete user info
emit BondRedeemed( _recipient, info.payout, 0 ); // emit bond data
return stakeOrSend( _recipient, _stake, info.payout ); // pay user everything due
} else { // if unfinished
// calculate payout vested
uint payout = info.payout.mul( percentVested ).div( 10000 );
// store updated deposit info
bondInfo[ _recipient ] = Bond({
payout: info.payout.sub( payout ),
vesting: info.vesting.sub( block.number.sub( info.lastBlock ) ),
lastBlock: block.number,
pricePaid: info.pricePaid
});
emit BondRedeemed( _recipient, payout, bondInfo[ _recipient ].payout );
return stakeOrSend( _recipient, _stake, payout );
}
}
/* ======== INTERNAL HELPER FUNCTIONS ======== */
/**
* @notice allow user to stake payout automatically
* @param _stake bool
* @param _amount uint
* @return uint
*/
function stakeOrSend( address _recipient, bool _stake, uint _amount ) internal returns ( uint ) {
if ( !_stake ) { // if user does not want to stake
IERC20( ROME ).transfer( _recipient, _amount ); // send payout
} else { // if user wants to stake
if ( useHelper ) { // use if staking warmup is 0
IERC20( ROME ).approve( stakingHelper, _amount );
IStakingHelper( stakingHelper ).stake( _amount, _recipient );
} else {
IERC20( ROME ).approve( staking, _amount );
IStaking( staking ).stake( _amount, _recipient );
}
}
return _amount;
}
/**
* @notice makes incremental adjustment to control variable
*/
function adjust() internal {
uint blockCanAdjust = adjustment.lastBlock.add( adjustment.buffer );
if( adjustment.rate != 0 && block.number >= blockCanAdjust ) {
uint initial = terms.controlVariable;
if ( adjustment.add ) {
terms.controlVariable = terms.controlVariable.add( adjustment.rate );
if ( terms.controlVariable >= adjustment.target ) {
adjustment.rate = 0;
}
} else {
terms.controlVariable = terms.controlVariable.sub( adjustment.rate );
if ( terms.controlVariable <= adjustment.target ) {
adjustment.rate = 0;
}
}
adjustment.lastBlock = block.number;
emit ControlVariableAdjustment( initial, terms.controlVariable, adjustment.rate, adjustment.add );
}
}
/**
* @notice reduce total debt
*/
function decayDebt() internal {
totalDebt = totalDebt.sub( debtDecay() );
lastDecay = block.number;
}
/* ======== VIEW FUNCTIONS ======== */
/**
* @notice determine maximum bond size
* @return uint
*/
function maxPayout() public view returns ( uint ) {
return IERC20( ROME ).totalSupply().mul( terms.maxPayout ).div( 100000 );
}
/**
* @notice calculate interest due for new bond
* @param _value uint
* @return uint
*/
function payoutFor( uint _value ) public view returns ( uint ) {
return FixedPoint.fraction( _value, bondPrice() ).decode112with18().div( 1e14 );
}
/**
* @notice calculate current bond premium
* @return price_ uint
*/
function bondPrice() public view returns ( uint price_ ) {
price_ = terms.controlVariable.mul( debtRatio() ).div( 1e5 );
if ( price_ < terms.minimumPrice ) {
price_ = terms.minimumPrice;
}
}
/**
* @notice calculate current bond price and remove floor if above
* @return price_ uint
*/
function _bondPrice() internal returns ( uint price_ ) {
price_ = terms.controlVariable.mul( debtRatio() ).div( 1e5 );
if ( price_ < terms.minimumPrice ) {
price_ = terms.minimumPrice;
} else if ( terms.minimumPrice != 0 ) {
terms.minimumPrice = 0;
}
}
/**
* @notice get asset price from chainlink
*/
function assetPrice() public view returns (int) {
( , int price, , , ) = priceFeed.latestRoundData();
return price;
}
/**
* @notice converts bond price to DAI value
* @return price_ uint
*/
function bondPriceInUSD() public view returns ( uint price_ ) {
if (bondCalculator == address(0)) {
price_ = bondPrice().mul( uint( assetPrice() ) ).mul( 1e6 );
} else {
price_ = bondPrice()
.mul( IBondCalculator( bondCalculator ).markdown( principle ) )
.mul( uint( assetPrice() ) )
.div( 1e12 );
}
}
/**
* @notice calculate current ratio of debt to ROME supply
* @return debtRatio_ uint
*/
function debtRatio() public view returns ( uint debtRatio_ ) {
debtRatio_ = FixedPoint.fraction(
currentDebt().mul( 1e9 ),
IERC20( ROME ).totalSupply()
).decode112with18().div( 1e18 );
}
/**
* @notice debt ratio in same terms as reserve bonds
* @return uint
*/
function standardizedDebtRatio() external view returns ( uint ) {
if (bondCalculator == address(0)) {
return debtRatio().mul( uint( assetPrice() ) ).div( 1e8 ); // ETH feed is 8 decimals
} else {
return debtRatio().mul( IBondCalculator( bondCalculator ).markdown( principle ) ).div( 1e9 );
}
}
/**
* @notice calculate debt factoring in decay
* @return uint
*/
function currentDebt() public view returns ( uint ) {
return totalDebt.sub( debtDecay() );
}
/**
* @notice amount to decay total debt by
* @return decay_ uint
*/
function debtDecay() public view returns ( uint decay_ ) {
uint blocksSinceLast = block.number.sub( lastDecay );
decay_ = totalDebt.mul( blocksSinceLast ).div( terms.vestingTerm );
if ( decay_ > totalDebt ) {
decay_ = totalDebt;
}
}
/**
* @notice calculate how far into vesting a depositor is
* @param _depositor address
* @return percentVested_ uint
*/
function percentVestedFor( address _depositor ) public view returns ( uint percentVested_ ) {
Bond memory bond = bondInfo[ _depositor ];
uint blocksSinceLast = block.number.sub( bond.lastBlock );
uint vesting = bond.vesting;
if ( vesting > 0 ) {
percentVested_ = blocksSinceLast.mul( 10000 ).div( vesting );
} else {
percentVested_ = 0;
}
}
/**
* @notice calculate amount of ROME available for claim by depositor
* @param _depositor address
* @return pendingPayout_ uint
*/
function pendingPayoutFor( address _depositor ) external view returns ( uint pendingPayout_ ) {
uint percentVested = percentVestedFor( _depositor );
uint payout = bondInfo[ _depositor ].payout;
if ( percentVested >= 10000 ) {
pendingPayout_ = payout;
} else {
pendingPayout_ = payout.mul( percentVested ).div( 10000 );
}
}
/* ======= AUXILLIARY ======= */
/**
* @notice allow anyone to send lost tokens (excluding principle or ROME) to the DAO
* @return bool
*/
function recoverLostToken( address _token ) external returns ( bool ) {
require( _token != ROME );
require( _token != principle );
IERC20( _token ).safeTransfer( DAO, IERC20( _token ).balanceOf( address(this) ) );
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.7.5;
interface IPolicy {
function policy() external view returns (address);
function renouncePolicy() external;
function pushPolicy( address newOwner_ ) external;
function pullPolicy() external;
}
contract Policy is IPolicy {
address internal _owner;
address internal _newOwner;
event OwnershipPushed(address indexed previousOwner, address indexed newOwner);
event OwnershipPulled(address indexed previousOwner, address indexed newOwner);
constructor () {
_owner = msg.sender;
emit OwnershipPushed( address(0), _owner );
}
function policy() public view override returns (address) {
return _owner;
}
modifier onlyPolicy() {
require( _owner == msg.sender, "Ownable: caller is not the owner" );
_;
}
function renouncePolicy() public virtual override onlyPolicy() {
emit OwnershipPushed( _owner, address(0) );
_owner = address(0);
}
function pushPolicy( address newOwner_ ) public virtual override onlyPolicy() {
require( newOwner_ != address(0), "Ownable: new owner is the zero address");
emit OwnershipPushed( _owner, newOwner_ );
_newOwner = newOwner_;
}
function pullPolicy() public virtual override {
require( msg.sender == _newOwner, "Ownable: must be new owner to pull");
emit OwnershipPulled( _owner, _newOwner );
_owner = _newOwner;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
import "../interfaces/IERC20Permit.sol";
import "./ERC20.sol";
import "../cryptography/EIP712.sol";
import "../cryptography/ECDSA.sol";
import "../libraries/Counters.sol";
/**
* @dev Implementation 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.
*
* _Available since v3.4._
*/
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
// solhint-disable-next-line var-name-mixedcase
bytes32 private immutable _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
/**
* @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
*
* It's a good idea to use the same `name` that is defined as the ERC20 token name.
*/
constructor(string memory name) EIP712(name, "1") {}
/**
* @dev See {IERC20Permit-permit}.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
/**
* @dev See {IERC20Permit-nonces}.
*/
function nonces(address owner) public view virtual override returns (uint256) {
return _nonces[owner].current();
}
/**
* @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}
/**
* @dev "Consume a nonce": return the current value and increment.
*
* _Available since v4.1._
*/
function _useNonce(address owner) internal virtual returns (uint256 current) {
Counters.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
import "../interfaces/IERC20.sol";
import "./SafeMath.sol";
import "./Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
library FullMath {
function fullMul(uint256 x, uint256 y) private pure returns (uint256 l, uint256 h) {
uint256 mm = mulmod(x, y, uint256(-1));
l = x * y;
h = mm - l;
if (mm < l) h -= 1;
}
function fullDiv(
uint256 l,
uint256 h,
uint256 d
) private pure returns (uint256) {
uint256 pow2 = d & -d;
d /= pow2;
l /= pow2;
l += h * ((-pow2) / pow2 + 1);
uint256 r = 1;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
r *= 2 - d * r;
return l * r;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 d
) internal pure returns (uint256) {
(uint256 l, uint256 h) = fullMul(x, y);
uint256 mm = mulmod(x, y, d);
if (mm > l) h -= 1;
l -= mm;
require(h < d, 'FullMath::mulDiv: overflow');
return fullDiv(l, h, d);
}
}
library FixedPoint {
struct uq112x112 {
uint224 _x;
}
struct uq144x112 {
uint256 _x;
}
uint8 private constant RESOLUTION = 112;
uint256 private constant Q112 = 0x10000000000000000000000000000;
uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000;
uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)
function decode(uq112x112 memory self) internal pure returns (uint112) {
return uint112(self._x >> RESOLUTION);
}
function decode112with18(uq112x112 memory self) internal pure returns (uint) {
return uint(self._x) / 5192296858534827;
}
function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {
require(denominator > 0, 'FixedPoint::fraction: division by zero');
if (numerator == 0) return FixedPoint.uq112x112(0);
if (numerator <= uint144(-1)) {
uint256 result = (numerator << RESOLUTION) / denominator;
require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
return uq112x112(uint224(result));
} else {
uint256 result = FullMath.mulDiv(numerator, Q112, denominator);
require(result <= uint224(-1), 'FixedPoint::fraction: overflow');
return uq112x112(uint224(result));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
* given `owner`'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.7.5;
import "../libraries/SafeMath.sol";
import "../interfaces/IERC20.sol";
abstract contract ERC20 is IERC20 {
using SafeMath for uint256;
// TODO comment actual hash value.
bytes32 constant private ERC20TOKEN_ERC1820_INTERFACE_ID = keccak256( "ERC20Token" );
mapping (address => uint256) internal _balances;
mapping (address => mapping (address => uint256)) internal _allowances;
uint256 internal _totalSupply;
string internal _name;
string internal _symbol;
uint8 internal immutable _decimals;
constructor (string memory name_, string memory symbol_, uint8 decimals_) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account_, uint256 ammount_) internal virtual {
require(account_ != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account_, ammount_);
_totalSupply = _totalSupply.add(ammount_);
_balances[account_] = _balances[account_].add(ammount_);
emit Transfer(address(0), account_, ammount_);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer( address from_, address to_, uint256 amount_ ) internal virtual { }
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.5;
import "./ECDSA.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
uint256 chainID;
assembly {
chainID := chainid()
}
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = chainID;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
uint256 chainID;
assembly {
chainID := chainid()
}
if (chainID == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
uint256 chainID;
assembly {
chainID := chainid()
}
return keccak256(abi.encode(typeHash, nameHash, versionHash, chainID, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.5;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s;
uint8 v;
assembly {
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
v := add(shr(255, vs), 27)
}
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./SafeMath.sol";
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
// The {SafeMath} overflow check can be skipped here, see the comment at the top
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/*
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
// Only used in the BondingCalculator.sol
function sqrrt(uint256 a) internal pure returns (uint c) {
if (a > 3) {
c = a;
uint b = add( div( a, 2), 1 );
while (b < c) {
c = b;
b = div( add( div( a, b ), b), 2 );
}
} else if (a != 0) {
c = 1;
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.5;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
// 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(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) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
function addressToString(address _address) internal pure returns(string memory) {
bytes32 _bytes = bytes32(uint256(_address));
bytes memory HEX = "0123456789abcdef";
bytes memory _addr = new bytes(42);
_addr[0] = '0';
_addr[1] = 'x';
for(uint256 i = 0; i < 20; i++) {
_addr[2+i*2] = HEX[uint8(_bytes[i + 12] >> 4)];
_addr[3+i*2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
}
return string(_addr);
}
}{
"optimizer": {
"enabled": true,
"runs": 9999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_ROME","type":"address"},{"internalType":"address","name":"_principle","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_DAO","type":"address"},{"internalType":"address","name":"_bondCalculator","type":"address"},{"internalType":"address","name":"_feed","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"deposit","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"expires","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"priceInUSD","type":"uint256"}],"name":"BondCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"priceInUSD","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"internalPrice","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"debtRatio","type":"uint256"}],"name":"BondPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remaining","type":"uint256"}],"name":"BondRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"initialBCV","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBCV","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustment","type":"uint256"},{"indexed":false,"internalType":"bool","name":"addition","type":"bool"}],"name":"ControlVariableAdjustment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipPulled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipPushed","type":"event"},{"inputs":[],"name":"DAO","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROME","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adjustment","outputs":[{"internalType":"bool","name":"add","type":"bool"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"buffer","type":"uint256"},{"internalType":"uint256","name":"lastBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondCalculator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bondInfo","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"},{"internalType":"uint256","name":"vesting","type":"uint256"},{"internalType":"uint256","name":"lastBlock","type":"uint256"},{"internalType":"uint256","name":"pricePaid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondPrice","outputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondPriceInUSD","outputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtDecay","outputs":[{"internalType":"uint256","name":"decay_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debtRatio","outputs":[{"internalType":"uint256","name":"debtRatio_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxPrice","type":"uint256"},{"internalType":"address","name":"_depositor","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_controlVariable","type":"uint256"},{"internalType":"uint256","name":"_vestingTerm","type":"uint256"},{"internalType":"uint256","name":"_minimumPrice","type":"uint256"},{"internalType":"uint256","name":"_maxPayout","type":"uint256"},{"internalType":"uint256","name":"_maxDebt","type":"uint256"},{"internalType":"uint256","name":"_initialDebt","type":"uint256"}],"name":"initializeBondTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastDecay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"payoutFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"pendingPayoutFor","outputs":[{"internalType":"uint256","name":"pendingPayout_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"percentVestedFor","outputs":[{"internalType":"uint256","name":"percentVested_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"policy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"principle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pullPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"pushPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"recoverLostToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_addition","type":"bool"},{"internalType":"uint256","name":"_increment","type":"uint256"},{"internalType":"uint256","name":"_target","type":"uint256"},{"internalType":"uint256","name":"_buffer","type":"uint256"}],"name":"setAdjustment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum MOVRBondDepository.PARAMETER","name":"_parameter","type":"uint8"},{"internalType":"uint256","name":"_input","type":"uint256"}],"name":"setBondTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staking","type":"address"},{"internalType":"bool","name":"_helper","type":"bool"}],"name":"setStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingHelper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"standardizedDebtRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"terms","outputs":[{"internalType":"uint256","name":"controlVariable","type":"uint256"},{"internalType":"uint256","name":"vestingTerm","type":"uint256"},{"internalType":"uint256","name":"minimumPrice","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"maxDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useHelper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101206040523480156200001257600080fd5b5060405162002d3938038062002d39833981810160405260c08110156200003857600080fd5b50805160208201516040808401516060850151608086015160a090960151600080546001600160a01b031916331780825594519697959693959294929391926001600160a01b0316917fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba908290a36001600160a01b038616620000ba57600080fd5b6001600160601b0319606087901b166080526001600160a01b038516620000e057600080fd5b6001600160601b0319606086901b1660a0526001600160a01b0384166200010657600080fd5b6001600160601b0319606085901b1660c0526001600160a01b0383166200012c57600080fd5b606083811b6001600160601b031990811660e05283821b1661010052600280546001600160a01b0319166001600160a01b0393841617905560805160a05160c05191831c9850821c9650901c93509182169116612b2b6200020e60003980610dda5280610e4652806113d6528061142a52806118415250806114eb528061178e525080610c69528061102b52806111dd52806112425250806105bd5280610e75528061105a52806111ba5280611459528061174c52508061150f528061170d52806118b05280611b615280611d045280611e155280611f595250612b2b6000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80638dbdbe6d11610145578063cea55f57116100bd578063d7ccfb0b1161008c578063e392a26211610071578063e392a262146105a3578063f5c2ab5b146105ab578063fc7b9c18146105b357610241565b8063d7ccfb0b14610593578063e0176de81461059b57610241565b8063cea55f5714610522578063d24378eb1461052a578063d4d863ce14610532578063d50256251461056057610241565b8063a15ad07711610114578063b4abccba116100f9578063b4abccba146104a8578063c5332b7c146104ce578063cd1234b3146104d657610241565b8063a15ad0771461047a578063a4b23980146104a057610241565b80638dbdbe6d14610430578063904b3ece1461046257806398fabd3a1461046a5780639d95fbd21461047257610241565b80634cf088d9116101d8578063759076e5116101a75780637927ebf81161018c5780637927ebf8146103d05780637b261727146103ed578063844b5c7c1461042857610241565b8063759076e5146103c057806377b81895146103c857610241565b80634cf088d914610382578063507930ec1461038a5780635beede08146103b057806361d027b3146103b857610241565b80631e321a0f116102145780631e321a0f146102dd5780631feed31f146103035780632f3f470a14610331578063451ee4a11461034d57610241565b8063016a42841461024657806301b88ee81461026a5780630505c8c9146102a25780631a3d0068146102aa575b600080fd5b61024e6105bb565b604080516001600160a01b039092168252519081900360200190f35b6102906004803603602081101561028057600080fd5b50356001600160a01b03166105df565b60408051918252519081900360200190f35b61024e610638565b6102db600480360360808110156102c057600080fd5b50803515159060208101359060408101359060600135610648565b005b6102db600480360360408110156102f357600080fd5b5060ff8135169060200135610785565b6102906004803603604081101561031957600080fd5b506001600160a01b03813516906020013515156108d6565b610339610acb565b604080519115158252519081900360200190f35b610355610aec565b60408051951515865260208601949094528484019290925260608401526080830152519081900360a00190f35b61024e610b04565b610290600480360360208110156103a057600080fd5b50356001600160a01b0316610b13565b6102db610ba5565b61024e610c67565b610290610c8b565b61024e610ca6565b610290600480360360208110156103e657600080fd5b5035610cb5565b6102db600480360360c081101561040357600080fd5b5080359060208101359060408101359060608101359060808101359060a00135610cda565b610290610dd6565b6102906004803603606081101561044657600080fd5b50803590602081013590604001356001600160a01b0316610f05565b6102906113d2565b61024e6114e9565b61024e61150d565b6102db6004803603602081101561049057600080fd5b50356001600160a01b0316611531565b6102db611648565b610339600480360360208110156104be57600080fd5b50356001600160a01b0316611709565b61024e61183f565b6104fc600480360360208110156104ec57600080fd5b50356001600160a01b0316611863565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61029061188a565b610290611938565b6102db6004803603604081101561054857600080fd5b506001600160a01b03813516906020013515156119be565b610568611b0a565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b610290611b1c565b610290611b4d565b610290611bea565b610290611c2f565b610290611c35565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806105eb83610b13565b6001600160a01b0384166000908152600f6020526040902054909150612710821061061857809250610631565b61062e6127106106288385611c3b565b90611c94565b92505b5050919050565b6000546001600160a01b03165b90565b6000546001600160a01b031633146106a7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6005546106bd906103e890610628906019611c3b565b831115806106cb5750826001145b61071c576040805162461bcd60e51b815260206004820152601360248201527f496e6372656d656e7420746f6f206c6172676500000000000000000000000000604482015290519081900360640190fd5b6040805160a0810182529415158086526020860185905290850183905260608501829052436080909501859052600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055600b92909255600c55600d55600e55565b6000546001600160a01b031633146107e4576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008260028111156107f257fe5b1415610843576127108110156108395760405162461bcd60e51b8152600401808060200182810382526024815260200180612aa86024913960400191505060405180910390fd5b60068190556108d2565b600182600281111561085157fe5b14156108b8576103e88111156108ae576040805162461bcd60e51b815260206004820181905260248201527f5061796f75742063616e6e6f742062652061626f766520312070657263656e74604482015290519081900360640190fd5b60088190556108d2565b60028260028111156108c657fe5b14156108d25760098190555b5050565b60006108e0612995565b506001600160a01b0383166000908152600f602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529061093385610b13565b905061271081106109c3576001600160a01b0385166000818152600f602090815260408083208381556001810184905560028101849055600301839055855181519081529182019290925281517f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b1929181900390910190a26109ba85858460000151611cfb565b92505050610ac5565b81516000906109da90612710906106289085611c3b565b905060405180608001604052806109fe83866000015161207390919063ffffffff16565b8152602001610a28610a1d86604001514361207390919063ffffffff16565b602087015190612073565b8152436020808301919091526060808701516040938401526001600160a01b038a166000818152600f84528490208551808255868501516001830155868601516002830155959092015160039092019190915582518581529182019390935281517f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b1929181900390910190a2610abf868683611cfb565b93505050505b92915050565b60045474010000000000000000000000000000000000000000900460ff1681565b600a54600b54600c54600d54600e5460ff9094169385565b6003546001600160a01b031681565b6000610b1d612995565b506001600160a01b0382166000908152600f602090815260408083208151608081018352815481526001820154938101939093526002810154918301829052600301546060830152909190610b73904390612073565b60208301519091508015610b9857610b918161062884612710611c3b565b9350610b9d565b600093505b505050919050565b6001546001600160a01b03163314610bee5760405162461bcd60e51b81526004018080602001828103825260228152602001806129f66022913960400191505060405180910390fd5b600154600080546040516001600160a01b0393841693909116917faa151555690c956fc3ea32f106bb9f119b5237a061eaa8557cff3e51e3792c8d91a3600154600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610ca1610c98611bea565b60105490612073565b905090565b6004546001600160a01b031681565b6000610ac5655af3107a4000610628610cd585610cd0611b1c565b6120d0565b612291565b6000546001600160a01b03163314610d39576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60055415610d8e576040805162461bcd60e51b815260206004820181905260248201527f426f6e6473206d75737420626520696e697469616c697a65642066726f6d2030604482015290519081900360640190fd5b6040805160a081018252878152602081018790529081018590526060810184905260800182905260059590955560069390935560079190915560085560095560105543601155565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e2d57610e26620f4240610e20610e18611938565b610e20611b1c565b90611c3b565b9050610645565b610ca164e8d4a51000610628610e41611938565b610e207f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166332da80a37f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610ed157600080fd5b505afa158015610ee5573d6000803e3d6000fd5b505050506040513d6020811015610efb57600080fd5b5051610e20611b1c565b60006001600160a01b038216610f62576040805162461bcd60e51b815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b610f6a6122be565b60095460105411801590610f7f575060095415155b610fd0576040805162461bcd60e51b815260206004820152601460248201527f4d61782063617061636974792072656163686564000000000000000000000000604482015290519081900360640190fd5b6000610fda610dd6565b90506000610fe66122d2565b9050808510156110275760405162461bcd60e51b8152600401808060200182810382526023815260200180612a856023913960400191505060405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631eec5a9a7f0000000000000000000000000000000000000000000000000000000000000000896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b1580156110be57600080fd5b505afa1580156110d2573d6000803e3d6000fd5b505050506040513d60208110156110e857600080fd5b5051905060006110f782610cb5565b905062989680811015611151576040805162461bcd60e51b815260206004820152600e60248201527f426f6e6420746f6f20736d616c6c000000000000000000000000000000000000604482015290519081900360640190fd5b611159611b4d565b8111156111ad576040805162461bcd60e51b815260206004820152600e60248201527f426f6e6420746f6f206c61726765000000000000000000000000000000000000604482015290519081900360640190fd5b6112026001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016337f00000000000000000000000000000000000000000000000000000000000000008b61230c565b604080517f6a20de920000000000000000000000000000000000000000000000000000000081523060048201526024810183905290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691636a20de9291604480830192600092919082900301818387803b15801561128957600080fd5b505af115801561129d573d6000803e3d6000fd5b50506010546112af925090508361239a565b601055604080516080810182526001600160a01b0388166000908152600f602052919091205481906112e1908461239a565b81526006805460208084019190915243604080850182905260609485018a90526001600160a01b038c166000908152600f845281902086518155928601516001840155850151600283015593909201516003909201919091555485916113469161239a565b604080518b8152905184917f1fec6dc81f140574bf43f6b1e420ae1dd47928b9d57db8cbd7b8611063b85ae5919081900360200190a461138461188a565b61138c6122d2565b611394610dd6565b6040517f375b221f40939bfd8f49723a17cf7bc6d576ebf72efe2cc3e991826f5b3f390a90600090a46113c56123f4565b93505050505b9392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661141d57610e266305f5e100610628611415611938565b610e2061188a565b610e26633b9aca006106287f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166332da80a37f00000000000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d60208110156114df57600080fd5b5051610e2061188a565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b03163314611590576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115d55760405162461bcd60e51b81526004018080602001828103825260268152602001806129d06026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba91a3600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146116a7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316141561174a57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316141561178957600080fd5b6118377f0000000000000000000000000000000000000000000000000000000000000000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b50516001600160a01b03851691906124d4565b506001919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f6020526000908152604090208054600182015460028301546003909301549192909184565b6000610ca1670de0b6b3a7640000610628610cd56118ae633b9aca00610e20610c8b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561190757600080fd5b505afa15801561191b573d6000803e3d6000fd5b505050506040513d602081101561193157600080fd5b50516120d0565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561198957600080fd5b505afa15801561199d573d6000803e3d6000fd5b505050506040513d60a08110156119b357600080fd5b506020015191505090565b6000546001600160a01b03163314611a1d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038216611a3057600080fd5b8015611aa95760048054740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909116177fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790556108d2565b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055600380546001600160a01b0384167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b60055460065460075460085460095485565b6000611b39620186a0610628611b3061188a565b60055490611c3b565b600754909150811015610645575060075490565b6000610ca1620186a06106286005600301547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb857600080fd5b505afa158015611bcc573d6000803e3d6000fd5b505050506040513d6020811015611be257600080fd5b505190611c3b565b600080611c026011544361207390919063ffffffff16565b600654601054919250611c19916106289084611c3b565b9150601054821115611c2b5760105491505b5090565b60115481565b60105481565b600082611c4a57506000610ac5565b82820282848281611c5757fe5b04146113cb5760405162461bcd60e51b8152600401808060200182810382526021815260200180612a646021913960400191505060405180910390fd5b6000808211611cea576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611cf357fe5b049392505050565b600082611dab577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb85846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611d7957600080fd5b505af1158015611d8d573d6000803e3d6000fd5b505050506040513d6020811015611da357600080fd5b5061206c9050565b60045474010000000000000000000000000000000000000000900460ff1615611f145760048054604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b039283169381019390935260248301859052517f00000000000000000000000000000000000000000000000000000000000000009091169163095ea7b39160448083019260209291908290030181600087803b158015611e5f57600080fd5b505af1158015611e73573d6000803e3d6000fd5b505050506040513d6020811015611e8957600080fd5b505060048054604080517f7acb77570000000000000000000000000000000000000000000000000000000081529283018590526001600160a01b0387811660248501529051911691637acb775791604480830192600092919082900301818387803b158015611ef757600080fd5b505af1158015611f0b573d6000803e3d6000fd5b5050505061206c565b600354604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201526024810185905290517f00000000000000000000000000000000000000000000000000000000000000009092169163095ea7b3916044808201926020929091908290030181600087803b158015611fa457600080fd5b505af1158015611fb8573d6000803e3d6000fd5b505050506040513d6020811015611fce57600080fd5b5050600354604080517f7acb7757000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b03878116602483015291519190921691637acb77579160448083019260209291908290030181600087803b15801561203f57600080fd5b505af1158015612053573d6000803e3d6000fd5b505050506040513d602081101561206957600080fd5b50505b5092915050565b6000828211156120ca576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6120d86129bd565b600082116121175760405162461bcd60e51b8152600401808060200182810382526026815260200180612a3e6026913960400191505060405180910390fd5b826121315750604080516020810190915260008152610ac5565b71ffffffffffffffffffffffffffffffffffff831161220257600082607085901b8161215957fe5b0490507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156121cd576040805162461bcd60e51b815260206004820152601e60248201527f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f770000604482015290519081900360640190fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050610ac5565b600061221e846e01000000000000000000000000000085612559565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156121cd576040805162461bcd60e51b815260206004820152601e60248201527f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f770000604482015290519081900360640190fd5b516612725dd1d243ab7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091160490565b6122c9610c98611bea565b60105543601155565b60006122e6620186a0610628611b3061188a565b6007549091508110156122fc5750600754610645565b6007541561064557600060075590565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526123949085906125ee565b50505050565b6000828201838110156113cb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600d54600e54600091612407919061239a565b600b549091501580159061241b5750804310155b156124d157600554600a5460ff161561245557600b5460055461243d9161239a565b6005819055600c5411612450576000600b555b612477565b600b5460055461246491612073565b6005819055600c5410612477576000600b555b43600e55600554600b54600a546040805185815260208101949094528381019290925260ff1615156060830152517fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a9181900360800190a1505b50565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526125549084906125ee565b505050565b6000806000612568868661269f565b915091506000848061257657fe5b86880990508281111561258a576001820391505b80830392508482106125e3576040805162461bcd60e51b815260206004820152601a60248201527f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f77000000000000604482015290519081900360640190fd5b6113c58383876126ea565b6060612643826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661275a9092919063ffffffff16565b8051909150156125545780806020019051602081101561266257600080fd5b50516125545760405162461bcd60e51b815260040180806020018281038252602a815260200180612acc602a913960400191505060405180910390fd5b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848609905083850292508281039150828110156126e2576001820391505b509250929050565b600081810382168083816126fa57fe5b04925080858161270657fe5b04945080816000038161271557fe5b60028581038087028203028087028203028087028203028087028203028087028203028087028203029586029003909402930460010193909302939093010292915050565b60606127698484600085612771565b949350505050565b6060824710156127b25760405162461bcd60e51b8152600401808060200182810382526026815260200180612a186026913960400191505060405180910390fd5b6127bb856128eb565b61280c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061286957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161282c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146128cb576040519150601f19603f3d011682016040523d82523d6000602084013e6128d0565b606091505b50915091506128e08282866128f1565b979650505050505050565b3b151590565b606083156129005750816113cb565b8251156129105782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561295a578181015183820152602001612942565b50505050905090810190601f1680156129875780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040805160208101909152600081529056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a206d757374206265206e6577206f776e657220746f2070756c6c416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212203dcfe22a1f5de2cb045d82ea390c8222b7cb84b8067ecaf93c5612bd104dad9164736f6c634300070500330000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d600000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af000000000000000000000000d4a7febd52efda82d6f8ace24908ae0aa5b4f95600000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f8bfbdc1e79777511c00ad8591cef888c2113c1
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102415760003560e01c80638dbdbe6d11610145578063cea55f57116100bd578063d7ccfb0b1161008c578063e392a26211610071578063e392a262146105a3578063f5c2ab5b146105ab578063fc7b9c18146105b357610241565b8063d7ccfb0b14610593578063e0176de81461059b57610241565b8063cea55f5714610522578063d24378eb1461052a578063d4d863ce14610532578063d50256251461056057610241565b8063a15ad07711610114578063b4abccba116100f9578063b4abccba146104a8578063c5332b7c146104ce578063cd1234b3146104d657610241565b8063a15ad0771461047a578063a4b23980146104a057610241565b80638dbdbe6d14610430578063904b3ece1461046257806398fabd3a1461046a5780639d95fbd21461047257610241565b80634cf088d9116101d8578063759076e5116101a75780637927ebf81161018c5780637927ebf8146103d05780637b261727146103ed578063844b5c7c1461042857610241565b8063759076e5146103c057806377b81895146103c857610241565b80634cf088d914610382578063507930ec1461038a5780635beede08146103b057806361d027b3146103b857610241565b80631e321a0f116102145780631e321a0f146102dd5780631feed31f146103035780632f3f470a14610331578063451ee4a11461034d57610241565b8063016a42841461024657806301b88ee81461026a5780630505c8c9146102a25780631a3d0068146102aa575b600080fd5b61024e6105bb565b604080516001600160a01b039092168252519081900360200190f35b6102906004803603602081101561028057600080fd5b50356001600160a01b03166105df565b60408051918252519081900360200190f35b61024e610638565b6102db600480360360808110156102c057600080fd5b50803515159060208101359060408101359060600135610648565b005b6102db600480360360408110156102f357600080fd5b5060ff8135169060200135610785565b6102906004803603604081101561031957600080fd5b506001600160a01b03813516906020013515156108d6565b610339610acb565b604080519115158252519081900360200190f35b610355610aec565b60408051951515865260208601949094528484019290925260608401526080830152519081900360a00190f35b61024e610b04565b610290600480360360208110156103a057600080fd5b50356001600160a01b0316610b13565b6102db610ba5565b61024e610c67565b610290610c8b565b61024e610ca6565b610290600480360360208110156103e657600080fd5b5035610cb5565b6102db600480360360c081101561040357600080fd5b5080359060208101359060408101359060608101359060808101359060a00135610cda565b610290610dd6565b6102906004803603606081101561044657600080fd5b50803590602081013590604001356001600160a01b0316610f05565b6102906113d2565b61024e6114e9565b61024e61150d565b6102db6004803603602081101561049057600080fd5b50356001600160a01b0316611531565b6102db611648565b610339600480360360208110156104be57600080fd5b50356001600160a01b0316611709565b61024e61183f565b6104fc600480360360208110156104ec57600080fd5b50356001600160a01b0316611863565b604080519485526020850193909352838301919091526060830152519081900360800190f35b61029061188a565b610290611938565b6102db6004803603604081101561054857600080fd5b506001600160a01b03813516906020013515156119be565b610568611b0a565b6040805195865260208601949094528484019290925260608401526080830152519081900360a00190f35b610290611b1c565b610290611b4d565b610290611bea565b610290611c2f565b610290611c35565b7f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a81565b6000806105eb83610b13565b6001600160a01b0384166000908152600f6020526040902054909150612710821061061857809250610631565b61062e6127106106288385611c3b565b90611c94565b92505b5050919050565b6000546001600160a01b03165b90565b6000546001600160a01b031633146106a7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6005546106bd906103e890610628906019611c3b565b831115806106cb5750826001145b61071c576040805162461bcd60e51b815260206004820152601360248201527f496e6372656d656e7420746f6f206c6172676500000000000000000000000000604482015290519081900360640190fd5b6040805160a0810182529415158086526020860185905290850183905260608501829052436080909501859052600a80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055600b92909255600c55600d55600e55565b6000546001600160a01b031633146107e4576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60008260028111156107f257fe5b1415610843576127108110156108395760405162461bcd60e51b8152600401808060200182810382526024815260200180612aa86024913960400191505060405180910390fd5b60068190556108d2565b600182600281111561085157fe5b14156108b8576103e88111156108ae576040805162461bcd60e51b815260206004820181905260248201527f5061796f75742063616e6e6f742062652061626f766520312070657263656e74604482015290519081900360640190fd5b60088190556108d2565b60028260028111156108c657fe5b14156108d25760098190555b5050565b60006108e0612995565b506001600160a01b0383166000908152600f602090815260408083208151608081018352815481526001820154938101939093526002810154918301919091526003015460608201529061093385610b13565b905061271081106109c3576001600160a01b0385166000818152600f602090815260408083208381556001810184905560028101849055600301839055855181519081529182019290925281517f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b1929181900390910190a26109ba85858460000151611cfb565b92505050610ac5565b81516000906109da90612710906106289085611c3b565b905060405180608001604052806109fe83866000015161207390919063ffffffff16565b8152602001610a28610a1d86604001514361207390919063ffffffff16565b602087015190612073565b8152436020808301919091526060808701516040938401526001600160a01b038a166000818152600f84528490208551808255868501516001830155868601516002830155959092015160039092019190915582518581529182019390935281517f51c99f515c87b0d95ba97f616edd182e8f161c4932eac17c6fefe9dab58b77b1929181900390910190a2610abf868683611cfb565b93505050505b92915050565b60045474010000000000000000000000000000000000000000900460ff1681565b600a54600b54600c54600d54600e5460ff9094169385565b6003546001600160a01b031681565b6000610b1d612995565b506001600160a01b0382166000908152600f602090815260408083208151608081018352815481526001820154938101939093526002810154918301829052600301546060830152909190610b73904390612073565b60208301519091508015610b9857610b918161062884612710611c3b565b9350610b9d565b600093505b505050919050565b6001546001600160a01b03163314610bee5760405162461bcd60e51b81526004018080602001828103825260228152602001806129f66022913960400191505060405180910390fd5b600154600080546040516001600160a01b0393841693909116917faa151555690c956fc3ea32f106bb9f119b5237a061eaa8557cff3e51e3792c8d91a3600154600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b7f000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af81565b6000610ca1610c98611bea565b60105490612073565b905090565b6004546001600160a01b031681565b6000610ac5655af3107a4000610628610cd585610cd0611b1c565b6120d0565b612291565b6000546001600160a01b03163314610d39576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60055415610d8e576040805162461bcd60e51b815260206004820181905260248201527f426f6e6473206d75737420626520696e697469616c697a65642066726f6d2030604482015290519081900360640190fd5b6040805160a081018252878152602081018790529081018590526060810184905260800182905260059590955560069390935560079190915560085560095560105543601155565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e2d57610e26620f4240610e20610e18611938565b610e20611b1c565b90611c3b565b9050610645565b610ca164e8d4a51000610628610e41611938565b610e207f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166332da80a37f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610ed157600080fd5b505afa158015610ee5573d6000803e3d6000fd5b505050506040513d6020811015610efb57600080fd5b5051610e20611b1c565b60006001600160a01b038216610f62576040805162461bcd60e51b815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b610f6a6122be565b60095460105411801590610f7f575060095415155b610fd0576040805162461bcd60e51b815260206004820152601460248201527f4d61782063617061636974792072656163686564000000000000000000000000604482015290519081900360640190fd5b6000610fda610dd6565b90506000610fe66122d2565b9050808510156110275760405162461bcd60e51b8152600401808060200182810382526023815260200180612a856023913960400191505060405180910390fd5b60007f000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af6001600160a01b0316631eec5a9a7f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a896040518363ffffffff1660e01b815260040180836001600160a01b031681526020018281526020019250505060206040518083038186803b1580156110be57600080fd5b505afa1580156110d2573d6000803e3d6000fd5b505050506040513d60208110156110e857600080fd5b5051905060006110f782610cb5565b905062989680811015611151576040805162461bcd60e51b815260206004820152600e60248201527f426f6e6420746f6f20736d616c6c000000000000000000000000000000000000604482015290519081900360640190fd5b611159611b4d565b8111156111ad576040805162461bcd60e51b815260206004820152600e60248201527f426f6e6420746f6f206c61726765000000000000000000000000000000000000604482015290519081900360640190fd5b6112026001600160a01b037f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a16337f000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af8b61230c565b604080517f6a20de920000000000000000000000000000000000000000000000000000000081523060048201526024810183905290516001600160a01b037f000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af1691636a20de9291604480830192600092919082900301818387803b15801561128957600080fd5b505af115801561129d573d6000803e3d6000fd5b50506010546112af925090508361239a565b601055604080516080810182526001600160a01b0388166000908152600f602052919091205481906112e1908461239a565b81526006805460208084019190915243604080850182905260609485018a90526001600160a01b038c166000908152600f845281902086518155928601516001840155850151600283015593909201516003909201919091555485916113469161239a565b604080518b8152905184917f1fec6dc81f140574bf43f6b1e420ae1dd47928b9d57db8cbd7b8611063b85ae5919081900360200190a461138461188a565b61138c6122d2565b611394610dd6565b6040517f375b221f40939bfd8f49723a17cf7bc6d576ebf72efe2cc3e991826f5b3f390a90600090a46113c56123f4565b93505050505b9392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661141d57610e266305f5e100610628611415611938565b610e2061188a565b610e26633b9aca006106287f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166332da80a37f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a6040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d60208110156114df57600080fd5b5051610e2061188a565b7f000000000000000000000000d4a7febd52efda82d6f8ace24908ae0aa5b4f95681565b7f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d681565b6000546001600160a01b03163314611590576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115d55760405162461bcd60e51b81526004018080602001828103825260268152602001806129d06026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba91a3600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000546001600160a01b031633146116a7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907fea8258f2d9ddb679928cf34b78cf645b7feda9acc828e4dd82d014eaae270eba908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60007f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d66001600160a01b0316826001600160a01b0316141561174a57600080fd5b7f00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a6001600160a01b0316826001600160a01b0316141561178957600080fd5b6118377f000000000000000000000000d4a7febd52efda82d6f8ace24908ae0aa5b4f956836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117fa57600080fd5b505afa15801561180e573d6000803e3d6000fd5b505050506040513d602081101561182457600080fd5b50516001600160a01b03851691906124d4565b506001919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f6020526000908152604090208054600182015460028301546003909301549192909184565b6000610ca1670de0b6b3a7640000610628610cd56118ae633b9aca00610e20610c8b565b7f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d66001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561190757600080fd5b505afa15801561191b573d6000803e3d6000fd5b505050506040513d602081101561193157600080fd5b50516120d0565b600080600260009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561198957600080fd5b505afa15801561199d573d6000803e3d6000fd5b505050506040513d60a08110156119b357600080fd5b506020015191505090565b6000546001600160a01b03163314611a1d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038216611a3057600080fd5b8015611aa95760048054740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909116177fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790556108d2565b600480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055600380546001600160a01b0384167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b60055460065460075460085460095485565b6000611b39620186a0610628611b3061188a565b60055490611c3b565b600754909150811015610645575060075490565b6000610ca1620186a06106286005600301547f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d66001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb857600080fd5b505afa158015611bcc573d6000803e3d6000fd5b505050506040513d6020811015611be257600080fd5b505190611c3b565b600080611c026011544361207390919063ffffffff16565b600654601054919250611c19916106289084611c3b565b9150601054821115611c2b5760105491505b5090565b60115481565b60105481565b600082611c4a57506000610ac5565b82820282848281611c5757fe5b04146113cb5760405162461bcd60e51b8152600401808060200182810382526021815260200180612a646021913960400191505060405180910390fd5b6000808211611cea576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381611cf357fe5b049392505050565b600082611dab577f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d66001600160a01b031663a9059cbb85846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611d7957600080fd5b505af1158015611d8d573d6000803e3d6000fd5b505050506040513d6020811015611da357600080fd5b5061206c9050565b60045474010000000000000000000000000000000000000000900460ff1615611f145760048054604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b039283169381019390935260248301859052517f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d69091169163095ea7b39160448083019260209291908290030181600087803b158015611e5f57600080fd5b505af1158015611e73573d6000803e3d6000fd5b505050506040513d6020811015611e8957600080fd5b505060048054604080517f7acb77570000000000000000000000000000000000000000000000000000000081529283018590526001600160a01b0387811660248501529051911691637acb775791604480830192600092919082900301818387803b158015611ef757600080fd5b505af1158015611f0b573d6000803e3d6000fd5b5050505061206c565b600354604080517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201526024810185905290517f0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d69092169163095ea7b3916044808201926020929091908290030181600087803b158015611fa457600080fd5b505af1158015611fb8573d6000803e3d6000fd5b505050506040513d6020811015611fce57600080fd5b5050600354604080517f7acb7757000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b03878116602483015291519190921691637acb77579160448083019260209291908290030181600087803b15801561203f57600080fd5b505af1158015612053573d6000803e3d6000fd5b505050506040513d602081101561206957600080fd5b50505b5092915050565b6000828211156120ca576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6120d86129bd565b600082116121175760405162461bcd60e51b8152600401808060200182810382526026815260200180612a3e6026913960400191505060405180910390fd5b826121315750604080516020810190915260008152610ac5565b71ffffffffffffffffffffffffffffffffffff831161220257600082607085901b8161215957fe5b0490507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156121cd576040805162461bcd60e51b815260206004820152601e60248201527f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f770000604482015290519081900360640190fd5b6040518060200160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815250915050610ac5565b600061221e846e01000000000000000000000000000085612559565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156121cd576040805162461bcd60e51b815260206004820152601e60248201527f4669786564506f696e743a3a6672616374696f6e3a206f766572666c6f770000604482015290519081900360640190fd5b516612725dd1d243ab7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091160490565b6122c9610c98611bea565b60105543601155565b60006122e6620186a0610628611b3061188a565b6007549091508110156122fc5750600754610645565b6007541561064557600060075590565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526123949085906125ee565b50505050565b6000828201838110156113cb576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600d54600e54600091612407919061239a565b600b549091501580159061241b5750804310155b156124d157600554600a5460ff161561245557600b5460055461243d9161239a565b6005819055600c5411612450576000600b555b612477565b600b5460055461246491612073565b6005819055600c5410612477576000600b555b43600e55600554600b54600a546040805185815260208101949094528381019290925260ff1615156060830152517fb923e581a0f83128e9e1d8297aa52b18d6744310476e0b54509c054cd7a93b2a9181900360800190a1505b50565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526125549084906125ee565b505050565b6000806000612568868661269f565b915091506000848061257657fe5b86880990508281111561258a576001820391505b80830392508482106125e3576040805162461bcd60e51b815260206004820152601a60248201527f46756c6c4d6174683a3a6d756c4469763a206f766572666c6f77000000000000604482015290519081900360640190fd5b6113c58383876126ea565b6060612643826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661275a9092919063ffffffff16565b8051909150156125545780806020019051602081101561266257600080fd5b50516125545760405162461bcd60e51b815260040180806020018281038252602a815260200180612acc602a913960400191505060405180910390fd5b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848609905083850292508281039150828110156126e2576001820391505b509250929050565b600081810382168083816126fa57fe5b04925080858161270657fe5b04945080816000038161271557fe5b60028581038087028203028087028203028087028203028087028203028087028203028087028203029586029003909402930460010193909302939093010292915050565b60606127698484600085612771565b949350505050565b6060824710156127b25760405162461bcd60e51b8152600401808060200182810382526026815260200180612a186026913960400191505060405180910390fd5b6127bb856128eb565b61280c576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061286957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161282c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146128cb576040519150601f19603f3d011682016040523d82523d6000602084013e6128d0565b606091505b50915091506128e08282866128f1565b979650505050505050565b3b151590565b606083156129005750816113cb565b8251156129105782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561295a578181015183820152602001612942565b50505050905090810190601f1680156129875780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040805160208101909152600081529056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a206d757374206265206e6577206f776e657220746f2070756c6c416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4669786564506f696e743a3a6672616374696f6e3a206469766973696f6e206279207a65726f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77536c697070616765206c696d69743a206d6f7265207468616e206d617820707269636556657374696e67206d757374206265206c6f6e676572207468616e20333620686f7572735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a26469706673582212203dcfe22a1f5de2cb045d82ea390c8222b7cb84b8067ecaf93c5612bd104dad9164736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d600000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af000000000000000000000000d4a7febd52efda82d6f8ace24908ae0aa5b4f95600000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f8bfbdc1e79777511c00ad8591cef888c2113c1
-----Decoded View---------------
Arg [0] : _ROME (address): 0x4a436073552044D5f2f49B176853ad3Ad473d9d6
Arg [1] : _principle (address): 0x98878B06940aE243284CA214f92Bb71a2b032B8A
Arg [2] : _treasury (address): 0xfbAD41e4Dd040BC80c89FcC6E90d152A746139aF
Arg [3] : _DAO (address): 0xD4a7FEbD52efda82d6f8acE24908aE0aa5b4f956
Arg [4] : _bondCalculator (address): 0x0000000000000000000000000000000000000000
Arg [5] : _feed (address): 0x3f8BFbDc1e79777511c00Ad8591cef888C2113C1
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000004a436073552044d5f2f49b176853ad3ad473d9d6
Arg [1] : 00000000000000000000000098878b06940ae243284ca214f92bb71a2b032b8a
Arg [2] : 000000000000000000000000fbad41e4dd040bc80c89fcc6e90d152a746139af
Arg [3] : 000000000000000000000000d4a7febd52efda82d6f8ace24908ae0aa5b4f956
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000003f8bfbdc1e79777511c00ad8591cef888c2113c1
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$809.23
Net Worth in MOVR
Token Allocations
ROME
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| MOVR | 100.00% | $11.15 | 72.577 | $809.23 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.