ERC-20
DeFi
Overview
Max Total Supply
11.80824052706386965 BTC++
Holders
533 ( 0.188%)
Market
Price
$57,671.17 @ 18.157638 ETH
Onchain Market Cap
$680,995.06
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0 BTC++Value
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
PProxyPausable
Compiler Version
v0.6.4+commit.1dca32f3
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-04-02 */ /** *Submitted for verification at Etherscan.io on 2020-04-02 */ // Sources flattened with buidler v1.2.0 https://buidler.dev // File @pie-dao/proxy/contracts/[email protected] pragma solidity ^0.6.2; contract PProxyStorage { function readString(bytes32 _key) public view returns(string memory) { return bytes32ToString(storageRead(_key)); } function setString(bytes32 _key, string memory _value) internal { storageSet(_key, stringToBytes32(_value)); } function readBool(bytes32 _key) public view returns(bool) { return storageRead(_key) == bytes32(uint256(1)); } function setBool(bytes32 _key, bool _value) internal { if(_value) { storageSet(_key, bytes32(uint256(1))); } else { storageSet(_key, bytes32(uint256(0))); } } function readAddress(bytes32 _key) public view returns(address) { return bytes32ToAddress(storageRead(_key)); } function setAddress(bytes32 _key, address _value) internal { storageSet(_key, addressToBytes32(_value)); } function storageRead(bytes32 _key) public view returns(bytes32) { bytes32 value; //solium-disable-next-line security/no-inline-assembly assembly { value := sload(_key) } return value; } function storageSet(bytes32 _key, bytes32 _value) internal { // targetAddress = _address; // No! bytes32 implAddressStorageKey = _key; //solium-disable-next-line security/no-inline-assembly assembly { sstore(implAddressStorageKey, _value) } } function bytes32ToAddress(bytes32 _value) public pure returns(address) { return address(uint160(uint256(_value))); } function addressToBytes32(address _value) public pure returns(bytes32) { return bytes32(uint256(_value)); } function stringToBytes32(string memory _value) public pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(_value); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(_value, 32)) } } function bytes32ToString(bytes32 _value) public pure returns (string memory) { bytes memory bytesString = new bytes(32); uint charCount = 0; for (uint256 j = 0; j < 32; j++) { byte char = byte(bytes32(uint(_value) * 2 ** (8 * j))); if (char != 0) { bytesString[charCount] = char; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (uint256 j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } } // File @pie-dao/proxy/contracts/[email protected] pragma solidity ^0.6.2; contract PProxy is PProxyStorage { bytes32 constant IMPLEMENTATION_SLOT = keccak256(abi.encodePacked("IMPLEMENTATION_SLOT")); bytes32 constant OWNER_SLOT = keccak256(abi.encodePacked("OWNER_SLOT")); modifier onlyProxyOwner() { require(msg.sender == readAddress(OWNER_SLOT), "PProxy.onlyProxyOwner: msg sender not owner"); _; } constructor () public { setAddress(OWNER_SLOT, msg.sender); } function getProxyOwner() public view returns (address) { return readAddress(OWNER_SLOT); } function setProxyOwner(address _newOwner) onlyProxyOwner public { setAddress(OWNER_SLOT, _newOwner); } function getImplementation() public view returns (address) { return readAddress(IMPLEMENTATION_SLOT); } function setImplementation(address _newImplementation) onlyProxyOwner public { setAddress(IMPLEMENTATION_SLOT, _newImplementation); } fallback () external payable { return internalFallback(); } function internalFallback() internal virtual { address contractAddr = readAddress(IMPLEMENTATION_SLOT); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize()) let result := delegatecall(gas(), contractAddr, ptr, calldatasize(), 0, 0) let size := returndatasize() returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } } // File @pie-dao/proxy/contracts/[email protected] pragma solidity ^0.6.2; contract PProxyPausable is PProxy { bytes32 constant PAUSED_SLOT = keccak256(abi.encodePacked("PAUSED_SLOT")); bytes32 constant PAUZER_SLOT = keccak256(abi.encodePacked("PAUZER_SLOT")); constructor() PProxy() public { setAddress(PAUZER_SLOT, msg.sender); } modifier onlyPauzer() { require(msg.sender == readAddress(PAUZER_SLOT), "PProxyPausable.onlyPauzer: msg sender not pauzer"); _; } modifier notPaused() { require(!readBool(PAUSED_SLOT), "PProxyPausable.notPaused: contract is paused"); _; } function getPauzer() public view returns (address) { return readAddress(PAUZER_SLOT); } function setPauzer(address _newPauzer) public onlyProxyOwner{ setAddress(PAUZER_SLOT, _newPauzer); } function renouncePauzer() public onlyPauzer { setAddress(PAUZER_SLOT, address(0)); } function getPaused() public view returns (bool) { return readBool(PAUSED_SLOT); } function setPaused(bool _value) public onlyPauzer { setBool(PAUSED_SLOT, _value); } function internalFallback() internal virtual override notPaused { super.internalFallback(); } } // File contracts/interfaces/IBFactory.sol pragma solidity ^0.6.4; interface IBFactory { function newBPool() external returns (address); } // File contracts/interfaces/IBPool.sol // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is disstributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.6.4; interface IBPool { function isBound(address token) external view returns(bool); function getBalance(address token) external view returns (uint); function rebind(address token, uint balance, uint denorm) external; function setSwapFee(uint swapFee) external; function setPublicSwap(bool _public) external; function bind(address token, uint balance, uint denorm) external; function unbind(address token) external; function getDenormalizedWeight(address token) external view returns (uint); function getTotalDenormalizedWeight() external view returns (uint); function getCurrentTokens() external view returns(address[] memory); function setController(address manager) external; function isPublicSwap() external view returns(bool); function getSwapFee() external view returns (uint256); function gulp(address token) external; function calcPoolOutGivenSingleIn( uint tokenBalanceIn, uint tokenWeightIn, uint poolSupply, uint totalWeight, uint tokenAmountIn, uint swapFee ) external pure returns (uint poolAmountOut); function calcSingleInGivenPoolOut( uint tokenBalanceIn, uint tokenWeightIn, uint poolSupply, uint totalWeight, uint poolAmountOut, uint swapFee ) external pure returns (uint tokenAmountIn); function calcSingleOutGivenPoolIn( uint tokenBalanceOut, uint tokenWeightOut, uint poolSupply, uint totalWeight, uint poolAmountIn, uint swapFee ) external pure returns (uint tokenAmountOut); function calcPoolInGivenSingleOut( uint tokenBalanceOut, uint tokenWeightOut, uint poolSupply, uint totalWeight, uint tokenAmountOut, uint swapFee ) external pure returns (uint poolAmountIn); } // File contracts/interfaces/IERC20.sol pragma solidity ^0.6.4; interface IERC20 { event Approval(address indexed _src, address indexed _dst, uint _amount); event Transfer(address indexed _src, address indexed _dst, uint _amount); function totalSupply() external view returns (uint); function balanceOf(address _whom) external view returns (uint); function allowance(address _src, address _dst) external view returns (uint); function approve(address _dst, uint _amount) external returns (bool); function transfer(address _dst, uint _amount) external returns (bool); function transferFrom( address _src, address _dst, uint _amount ) external returns (bool); } // File contracts/Ownable.sol pragma solidity ^0.6.4; // TODO move this generic contract to a seperate repo with all generic smart contracts contract Ownable { bytes32 constant public oSlot = keccak256("Ownable.storage.location"); event OwnerChanged(address indexed previousOwner, address indexed newOwner); // Ownable struct struct os { address owner; } modifier onlyOwner(){ require(msg.sender == los().owner, "Ownable.onlyOwner: msg.sender not owner"); _; } /** @notice Transfer ownership to a new address @param _newOwner Address of the new owner */ function transferOwnership(address _newOwner) onlyOwner external { _setOwner(_newOwner); } /** @notice Internal method to set the owner @param _newOwner Address of the new owner */ function _setOwner(address _newOwner) internal { emit OwnerChanged(los().owner, _newOwner); los().owner = _newOwner; } /** @notice Load ownable storage @return s Storage pointer to the Ownable storage struct */ function los() internal pure returns (os storage s) { bytes32 loc = oSlot; assembly { s_slot := loc } } } // File contracts/interfaces/IPSmartPool.sol pragma solidity ^0.6.4; interface IPSmartPool is IERC20 { function joinPool(uint256 _amount) external; function exitPool(uint256 _amount) external; function getController() external view returns(address); function getTokens() external view returns(address[] memory); function calcTokensForAmount(uint256 _amount) external view returns(address[] memory tokens, uint256[] memory amounts); } // File contracts/PCTokenStorage.sol pragma solidity ^0.6.4; contract PCTokenStorage { bytes32 constant public ptSlot = keccak256("PCToken.storage.location"); struct pts { string name; string symbol; uint256 totalSupply; mapping(address => uint256) balance; mapping(address => mapping(address=>uint256)) allowance; } /** @notice Load pool token storage @return s Storage pointer to the pool token struct */ function lpts() internal pure returns (pts storage s) { bytes32 loc = ptSlot; assembly { s_slot := loc } } } // File contracts/PCToken.sol // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity ^0.6.4; // Highly opinionated token implementation // Based on the balancer Implementation contract PCToken is IERC20, PCTokenStorage { event Approval(address indexed _src, address indexed _dst, uint _amount); event Transfer(address indexed _src, address indexed _dst, uint _amount); uint8 public constant decimals = 18; uint public constant BONE = 10**18; uint public constant MAX_BOUND_TOKENS = 8; uint public constant MIN_WEIGHT = BONE; uint public constant MAX_WEIGHT = BONE * 50; uint public constant MAX_TOTAL_WEIGHT = BONE * 50; uint public constant MIN_BALANCE = BONE / 10**6; uint public constant MAX_BALANCE = BONE * 10**12; uint public constant MIN_POOL_SUPPLY = BONE; function badd(uint a, uint b) internal pure returns (uint) { uint c = a + b; require(c >= a, "ERR_ADD_OVERFLOW"); return c; } function bsub(uint a, uint b) internal pure returns (uint) { (uint c, bool flag) = bsubSign(a, b); require(!flag, "ERR_SUB_UNDERFLOW"); return c; } function bsubSign(uint a, uint b) internal pure returns (uint, bool) { if (a >= b) { return (a - b, false); } else { return (b - a, true); } } function bmul(uint a, uint b) internal pure returns (uint) { uint c0 = a * b; require(a == 0 || c0 / a == b, "ERR_MUL_OVERFLOW"); uint c1 = c0 + (BONE / 2); require(c1 >= c0, "ERR_MUL_OVERFLOW"); uint c2 = c1 / BONE; return c2; } function bdiv(uint a, uint b) internal pure returns (uint) { require(b != 0, "ERR_DIV_ZERO"); uint c0 = a * BONE; require(a == 0 || c0 / a == BONE, "ERR_DIV_INTERNAL"); // bmul overflow uint c1 = c0 + (b / 2); require(c1 >= c0, "ERR_DIV_INTERNAL"); // badd require uint c2 = c1 / b; return c2; } function _mint(uint _amount) internal { pts storage s = lpts(); s.balance[address(this)] = badd(s.balance[address(this)], _amount); s.totalSupply = badd(s.totalSupply, _amount); emit Transfer(address(0), address(this), _amount); } function _burn(uint _amount) internal { pts storage s = lpts(); require(s.balance[address(this)] >= _amount, "ERR_INSUFFICIENT_BAL"); s.balance[address(this)] = bsub(s.balance[address(this)], _amount); s.totalSupply = bsub(s.totalSupply, _amount); emit Transfer(address(this), address(0), _amount); } function _move(address _src, address _dst, uint _amount) internal { pts storage s = lpts(); require(s.balance[_src] >= _amount, "ERR_INSUFFICIENT_BAL"); s.balance[_src] = bsub(s.balance[_src], _amount); s.balance[_dst] = badd(s.balance[_dst], _amount); emit Transfer(_src, _dst, _amount); } function _push(address _to, uint _amount) internal { _move(address(this), _to, _amount); } function _pull(address _from, uint _amount) internal { _move(_from, address(this), _amount); } function allowance(address _src, address _dst) external view override returns (uint) { return lpts().allowance[_src][_dst]; } function balanceOf(address _whom) external view override returns (uint) { return lpts().balance[_whom]; } function totalSupply() public view override returns (uint) { return lpts().totalSupply; } function name() external view returns (string memory) { return lpts().name; } function symbol() external view returns (string memory) { return lpts().symbol; } function approve(address _dst, uint _amount) external override returns (bool) { lpts().allowance[msg.sender][_dst] = _amount; emit Approval(msg.sender, _dst, _amount); return true; } function increaseApproval(address _dst, uint _amount) external returns (bool) { pts storage s = lpts(); s.allowance[msg.sender][_dst] = badd(s.allowance[msg.sender][_dst], _amount); emit Approval(msg.sender, _dst, s.allowance[msg.sender][_dst]); return true; } function decreaseApproval(address _dst, uint _amount) external returns (bool) { pts storage s = lpts(); uint oldValue = s.allowance[msg.sender][_dst]; if (_amount > oldValue) { s.allowance[msg.sender][_dst] = 0; } else { s.allowance[msg.sender][_dst] = bsub(oldValue, _amount); } emit Approval(msg.sender, _dst, s.allowance[msg.sender][_dst]); return true; } function transfer(address _dst, uint _amount) external override returns (bool) { _move(msg.sender, _dst, _amount); return true; } function transferFrom(address _src, address _dst, uint _amount) external override returns (bool) { pts storage s = lpts(); require(msg.sender == _src || _amount <= s.allowance[_src][msg.sender], "ERR_PCTOKEN_BAD_CALLER"); _move(_src, _dst, _amount); if (msg.sender != _src && s.allowance[_src][msg.sender] != uint256(-1)) { s.allowance[_src][msg.sender] = bsub(s.allowance[_src][msg.sender], _amount); emit Approval(msg.sender, _dst, s.allowance[_src][msg.sender]); } return true; } } // File contracts/ReentryProtection.sol pragma solidity ^0.6.4; // TODO move this generic contract to a seperate repo with all generic smart contracts contract ReentryProtection { bytes32 constant public rpSlot = keccak256("ReentryProtection.storage.location"); // reentry protection storage struct rps { uint256 lockCounter; } modifier noReentry { // Use counter to only write to storage once lrps().lockCounter ++; uint256 lockValue = lrps().lockCounter; _; require(lockValue == lrps().lockCounter, "ReentryProtection.noReentry: reentry detected"); } /** @notice Load reentry protection storage @return s Pointer to the reentry protection storage struct */ function lrps() internal pure returns (rps storage s) { bytes32 loc = rpSlot; assembly { s_slot := loc } } } // File contracts/smart-pools/PBasicSmartPool.sol pragma solidity ^0.6.4; contract PBasicSmartPool is IPSmartPool, PCToken, ReentryProtection { // P Basic Smart Struct bytes32 constant public pbsSlot = keccak256("PBasicSmartPool.storage.location"); struct pbs { IBPool bPool; address controller; address publicSwapSetter; address tokenBinder; } modifier ready() { require(address(lpbs().bPool) != address(0), "PBasicSmartPool.ready: not ready"); _; } event LOG_JOIN( address indexed caller, address indexed tokenIn, uint256 tokenAmountIn ); event LOG_EXIT( address indexed caller, address indexed tokenOut, uint256 tokenAmountOut ); event TokensApproved(); event ControllerChanged(address indexed previousController, address indexed newController); event PublicSwapSetterChanged(address indexed previousSetter, address indexed newSetter); event TokenBinderChanged(address indexed previousTokenBinder, address indexed newTokenBinder); event PublicSwapSet(address indexed setter, bool indexed value); event SwapFeeSet(address indexed setter, uint256 newFee); event PoolJoined(address indexed from, uint256 amount); event PoolExited(address indexed from, uint256 amount); modifier onlyController() { require(msg.sender == lpbs().controller, "PBasicSmartPool.onlyController: not controller"); _; } modifier onlyPublicSwapSetter() { require(msg.sender == lpbs().publicSwapSetter, "PBasicSmartPool.onlyPublicSwapSetter: not public swap setter"); _; } modifier onlyTokenBinder() { require(msg.sender == lpbs().tokenBinder, "PBasicSmartPool.onlyTokenBinder: not token binder"); _; } /** @notice Initialises the contract @param _bPool Address of the underlying balancer pool @param _name Name for the smart pool token @param _symbol Symbol for the smart pool token @param _initialSupply Initial token supply to mint */ function init(address _bPool, string calldata _name, string calldata _symbol, uint256 _initialSupply) external { pbs storage s = lpbs(); require(address(s.bPool) == address(0), "PBasicSmartPool.init: already initialised"); s.bPool = IBPool(_bPool); s.controller = msg.sender; s.publicSwapSetter = msg.sender; s.tokenBinder = msg.sender; lpts().name = _name; lpts().symbol = _symbol; _mintPoolShare(_initialSupply); _pushPoolShare(msg.sender, _initialSupply); } /** @notice Sets approval to all tokens to the underlying balancer pool @dev It uses this function to save on gas in joinPool */ function approveTokens() public { IBPool bPool = lpbs().bPool; address[] memory tokens = bPool.getCurrentTokens(); for(uint256 i = 0; i < tokens.length; i ++) { IERC20(tokens[i]).approve(address(bPool), uint256(-1)); } emit TokensApproved(); } /** @notice Sets the controller address. Can only be set by the current controller @param _controller Address of the new controller */ function setController(address _controller) onlyController noReentry external { emit ControllerChanged(lpbs().controller, _controller); lpbs().controller = _controller; } /** @notice Sets public swap setter address. Can only be set by the controller @param _newPublicSwapSetter Address of the new public swap setter */ function setPublicSwapSetter(address _newPublicSwapSetter) onlyController external { emit PublicSwapSetterChanged(lpbs().publicSwapSetter, _newPublicSwapSetter); lpbs().publicSwapSetter = _newPublicSwapSetter; } /** @notice Sets the token binder address. Can only be set by the controller @param _newTokenBinder Address of the new token binder */ function setTokenBinder(address _newTokenBinder) onlyController external { emit TokenBinderChanged(lpbs().tokenBinder, _newTokenBinder); lpbs().tokenBinder = _newTokenBinder; } /** @notice Enables or disables public swapping on the underlying balancer pool. Can only be set by the controller @param _public Public or not */ function setPublicSwap(bool _public) onlyPublicSwapSetter external { emit PublicSwapSet(msg.sender, _public); lpbs().bPool.setPublicSwap(_public); } /** @notice Set the swap fee on the underlying balancer pool. Can only be called by the controller @param _swapFee The new swap fee */ function setSwapFee(uint256 _swapFee) onlyController external { emit SwapFeeSet(msg.sender, _swapFee); lpbs().bPool.setSwapFee(_swapFee); } /** @notice Mints pool shares in exchange for underlying assets @param _amount Amount of pool shares to mint */ function joinPool(uint256 _amount) external override virtual ready { _joinPool(_amount); } /** @notice Internal join pool function. See joinPool for more info @param _amount Amount of pool shares to mint */ function _joinPool(uint256 _amount) internal virtual ready { IBPool bPool = lpbs().bPool; uint poolTotal = totalSupply(); uint ratio = bdiv(_amount, poolTotal); require(ratio != 0); address[] memory tokens = bPool.getCurrentTokens(); for (uint i = 0; i < tokens.length; i++) { address t = tokens[i]; uint bal = bPool.getBalance(t); uint tokenAmountIn = bmul(ratio, bal); emit LOG_JOIN(msg.sender, t, tokenAmountIn); _pullUnderlying(t, msg.sender, tokenAmountIn, bal); } _mintPoolShare(_amount); _pushPoolShare(msg.sender, _amount); emit PoolJoined(msg.sender, _amount); } /** @notice Burns pool shares and sends back the underlying assets @param _amount Amount of pool tokens to burn */ function exitPool(uint256 _amount) external override ready noReentry { IBPool bPool = lpbs().bPool; uint poolTotal = totalSupply(); uint ratio = bdiv(_amount, poolTotal); require(ratio != 0); _pullPoolShare(msg.sender, _amount); _burnPoolShare(_amount); address[] memory tokens = bPool.getCurrentTokens(); for (uint i = 0; i < tokens.length; i++) { address t = tokens[i]; uint bal = bPool.getBalance(t); uint tAo = bmul(ratio, bal); emit LOG_EXIT(msg.sender, t, tAo); _pushUnderlying(t, msg.sender, tAo, bal); } emit PoolExited(msg.sender, _amount); } /** @notice Bind a token to the underlying balancer pool. Can only be called by the token binder @param _token Token to bind @param _balance Amount to bind @param _denorm Denormalised weight */ function bind(address _token, uint256 _balance, uint256 _denorm) external onlyTokenBinder { IBPool bPool = lpbs().bPool; IERC20 token = IERC20(_token); token.transferFrom(msg.sender, address(this), _balance); token.approve(address(bPool), uint256(-1)); bPool.bind(_token, _balance, _denorm); } /** @notice Rebind a token to the pool @param _token Token to bind @param _balance Amount to bind @param _denorm Denormalised weight */ function rebind(address _token, uint256 _balance, uint256 _denorm) external onlyTokenBinder { IBPool bPool = lpbs().bPool; IERC20 token = IERC20(_token); // gulp old non acounted for token balance in the contract bPool.gulp(_token); uint256 oldBalance = token.balanceOf(address(bPool)); // If tokens need to be pulled from msg.sender if(_balance > oldBalance) { token.transferFrom(msg.sender, address(this), bsub(_balance, oldBalance)); token.approve(address(bPool), uint256(-1)); } bPool.rebind(_token, _balance, _denorm); // If any tokens are in this contract send them to msg.sender uint256 tokenBalance = token.balanceOf(address(this)); if(tokenBalance > 0) { token.transfer(msg.sender, tokenBalance); } } /** @notice Unbind a token @param _token Token to unbind */ function unbind(address _token) external onlyTokenBinder { IBPool bPool = lpbs().bPool; IERC20 token = IERC20(_token); // unbind the token in the bPool bPool.unbind(_token); // If any tokens are in this contract send them to msg.sender uint256 tokenBalance = token.balanceOf(address(this)); if(tokenBalance > 0) { token.transfer(msg.sender, tokenBalance); } } function getTokens() external view override returns(address[] memory) { return lpbs().bPool.getCurrentTokens(); } /** @notice Gets the underlying assets and amounts to mint specific pool shares. @param _amount Amount of pool shares to calculate the values for @return tokens The addresses of the tokens @return amounts The amounts of tokens needed to mint that amount of pool shares */ function calcTokensForAmount(uint256 _amount) external view override returns(address[] memory tokens, uint256[] memory amounts) { tokens = lpbs().bPool.getCurrentTokens(); amounts = new uint256[](tokens.length); uint256 ratio = bdiv(_amount, totalSupply()); for(uint256 i = 0; i < tokens.length; i ++) { address t = tokens[i]; uint256 bal = lpbs().bPool.getBalance(t); uint256 amount = bmul(ratio, bal); amounts[i] = amount; } } /** @notice Get the address of the controller @return The address of the pool */ function getController() external view override returns(address) { return lpbs().controller; } /** @notice Get the address of the public swap setter @return The public swap setter address */ function getPublicSwapSetter() external view returns(address) { return lpbs().publicSwapSetter; } /** @notice Get the address of the token binder @return The token binder address */ function getTokenBinder() external view returns(address) { return lpbs().tokenBinder; } /** @notice Get if public swapping is enabled @return If public swapping is enabled */ function isPublicSwap() external view returns (bool) { return lpbs().bPool.isPublicSwap(); } /** @notice Get the current swap fee @return The current swap fee */ function getSwapFee() external view returns (uint256) { return lpbs().bPool.getSwapFee(); } /** @notice Get the address of the underlying Balancer pool @return The address of the underlying balancer pool */ function getBPool() external view returns(address) { return address(lpbs().bPool); } /** @notice Pull the underlying token from an address and rebind it to the balancer pool @param _token Address of the token to pull @param _from Address to pull the token from @param _amount Amount of token to pull @param _tokenBalance Balance of the token already in the balancer pool */ function _pullUnderlying(address _token, address _from, uint256 _amount, uint256 _tokenBalance) internal { IBPool bPool = lpbs().bPool; // Gets current Balance of token i, Bi, and weight of token i, Wi, from BPool. uint tokenWeight = bPool.getDenormalizedWeight(_token); bool xfer = IERC20(_token).transferFrom(_from, address(this), _amount); require(xfer, "ERR_ERC20_FALSE"); bPool.rebind(_token, badd(_tokenBalance, _amount), tokenWeight); } /** @notice Push a underlying token and rebind the token to the balancer pool @param _token Address of the token to push @param _to Address to pull the token to @param _amount Amount of token to push @param _tokenBalance Balance of the token already in the balancer pool */ function _pushUnderlying(address _token, address _to, uint256 _amount, uint256 _tokenBalance) internal { IBPool bPool = lpbs().bPool; // Gets current Balance of token i, Bi, and weight of token i, Wi, from BPool. uint tokenWeight = bPool.getDenormalizedWeight(_token); bPool.rebind(_token, bsub(_tokenBalance, _amount), tokenWeight); bool xfer = IERC20(_token).transfer(_to, _amount); require(xfer, "ERR_ERC20_FALSE"); } /** @notice Pull pool shares @param _from Address to pull pool shares from @param _amount Amount of pool shares to pull */ function _pullPoolShare(address _from, uint256 _amount) internal { _pull(_from, _amount); } /** @notice Burn pool shares @param _amount Amount of pool shares to burn */ function _burnPoolShare(uint256 _amount) internal { _burn(_amount); } /** @notice Mint pool shares @param _amount Amount of pool shares to mint */ function _mintPoolShare(uint256 _amount) internal { _mint(_amount); } /** @notice Push pool shares to account @param _to Address to push the pool shares to @param _amount Amount of pool shares to push */ function _pushPoolShare(address _to, uint256 _amount) internal { _push(_to, _amount); } /** @notice Load PBasicPool storage @return s Pointer to the storage struct */ function lpbs() internal pure returns (pbs storage s) { bytes32 loc = pbsSlot; assembly { s_slot := loc } } } // File contracts/smart-pools/PCappedSmartPool.sol pragma solidity ^0.6.4; contract PCappedSmartPool is PBasicSmartPool { bytes32 constant public pcsSlot = keccak256("PCappedSmartPool.storage.location"); event CapChanged(address indexed setter, uint256 oldCap, uint256 newCap); struct pcs { uint256 cap; } modifier withinCap() { _; require(totalSupply() < lpcs().cap, "PCappedSmartPool.withinCap: Cap limit reached"); } /** @notice Set the maximum cap of the contract @param _cap New cap in wei */ function setCap(uint256 _cap) onlyController external { emit CapChanged(msg.sender, lpcs().cap, _cap); lpcs().cap = _cap; } /** @notice Takes underlying assets and mints smart pool tokens. Enforces the cap @param _amount Amount of pool tokens to mint */ function joinPool(uint256 _amount) external override withinCap { super._joinPool(_amount); } /** @notice Get the current cap @return The current cap in wei */ function getCap() external view returns(uint256) { return lpcs().cap; } /** @notice Load the PCappedSmartPool storage @return s Pointer to the storage struct */ function lpcs() internal pure returns (pcs storage s) { bytes32 loc = pcsSlot; assembly { s_slot := loc } } } // File contracts/factory/PProxiedFactory.sol pragma solidity ^0.6.4; contract PProxiedFactory is Ownable { IBFactory public balancerFactory; address public smartPoolImplementation; mapping(address => bool) public isPool; address[] public pools; event SmartPoolCreated(address indexed poolAddress, string name, string symbol); function init(address _balancerFactory) public { require(smartPoolImplementation == address(0), "Already initialised"); _setOwner(msg.sender); balancerFactory = IBFactory(_balancerFactory); PCappedSmartPool implementation = new PCappedSmartPool(); // function init(address _bPool, string calldata _name, string calldata _symbol, uint256 _initialSupply) external { implementation.init(address(0), "IMPL", "IMPL", 1 ether); smartPoolImplementation = address(implementation); } function newProxiedSmartPool( string memory _name, string memory _symbol, uint256 _initialSupply, address[] memory _tokens, uint256[] memory _amounts, uint256[] memory _weights, uint256 _cap ) public onlyOwner returns(address) { // Deploy proxy contract PProxyPausable proxy = new PProxyPausable(); // Setup proxy proxy.setImplementation(smartPoolImplementation); proxy.setPauzer(msg.sender); proxy.setProxyOwner(msg.sender); // Setup balancer pool address balancerPoolAddress = balancerFactory.newBPool(); IBPool bPool = IBPool(balancerPoolAddress); for(uint256 i = 0; i < _tokens.length; i ++) { IERC20 token = IERC20(_tokens[i]); // Transfer tokens to this contract token.transferFrom(msg.sender, address(this), _amounts[i]); // Approve the balancer pool token.approve(balancerPoolAddress, uint256(-1)); // Bind tokens bPool.bind(_tokens[i], _amounts[i], _weights[i]); } bPool.setController(address(proxy)); // Setup smart pool PCappedSmartPool smartPool = PCappedSmartPool(address(proxy)); smartPool.init(balancerPoolAddress, _name, _symbol, _initialSupply); smartPool.setCap(_cap); smartPool.setPublicSwapSetter(msg.sender); smartPool.setTokenBinder(msg.sender); smartPool.setController(msg.sender); smartPool.approveTokens(); isPool[address(smartPool)] = true; pools.push(address(smartPool)); emit SmartPoolCreated(address(smartPool), _name, _symbol); smartPool.transfer(msg.sender, _initialSupply); return address(smartPool); } } // File contracts/interfaces/IUniswapFactory.sol pragma solidity ^0.6.4; interface IUniswapFactory { // Create Exchange function createExchange(address token) external returns (address exchange); // Get Exchange and Token Info function getExchange(address token) external view returns (address exchange); function getToken(address exchange) external view returns (address token); function getTokenWithId(uint256 tokenId) external view returns (address token); // Never use function initializeFactory(address template) external; } // File contracts/interfaces/IUniswapExchange.sol pragma solidity ^0.6.4; interface IUniswapExchange { // Address of ERC20 token sold on this exchange function tokenAddress() external view returns (address token); // Address of Uniswap Factory function factoryAddress() external view returns (address factory); // Provide Liquidity function addLiquidity(uint256 min_liquidity, uint256 max_tokens, uint256 deadline) external payable returns (uint256); function removeLiquidity(uint256 amount, uint256 min_eth, uint256 min_tokens, uint256 deadline) external returns (uint256, uint256); // Get Prices function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought); function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold); function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought); function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold); // Trade ETH to ERC20 function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) external payable returns (uint256 tokens_bought); function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256 tokens_bought); function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline) external payable returns (uint256 eth_sold); function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256 eth_sold); // Trade ERC20 to ETH function tokenToEthSwapInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline) external returns (uint256 eth_bought); function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient) external returns (uint256 eth_bought); function tokenToEthSwapOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline) external returns (uint256 tokens_sold); function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256 tokens_sold); // Trade ERC20 to ERC20 function tokenToTokenSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address token_addr) external returns (uint256 tokens_bought); function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_bought); function tokenToTokenSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address token_addr) external returns (uint256 tokens_sold); function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_sold); // Trade ERC20 to Custom Pool function tokenToExchangeSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address exchange_addr) external returns (uint256 tokens_bought); function tokenToExchangeTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_bought); function tokenToExchangeSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address exchange_addr) external returns (uint256 tokens_sold); function tokenToExchangeTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_sold); // ERC20 comaptibility for liquidity tokens // bytes32 public name; // bytes32 public symbol; // uint256 public decimals; function transfer(address _to, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 value) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function allowance(address _owner, address _spender) external view returns (uint256); function balanceOf(address _owner) external view returns (uint256); function totalSupply() external view returns (uint256); // Never use function setup(address token_addr) external; } // File contracts/recipes/PUniswapPoolRecipe.sol pragma solidity ^0.6.4; // Takes ETH and mints smart pool tokens contract PUniswapPoolRecipe { bytes32 constant public uprSlot = keccak256("PUniswapPoolRecipe.storage.location"); // Uniswap pool recipe struct struct uprs { IPSmartPool pool; IUniswapFactory uniswapFactory; } function init(address _pool, address _uniswapFactory) public virtual { uprs storage s = luprs(); require(address(s.pool) == address(0), "already initialised"); s.pool = IPSmartPool(_pool); s.uniswapFactory = IUniswapFactory(_uniswapFactory); } // Using same interface as Uniswap for compatibility function ethToTokenTransferOutput(uint256 _tokens_bought, uint256 _deadline, address _recipient) public payable returns (uint256 eth_sold) { uprs storage s = luprs(); require(_deadline >= block.timestamp); (address[] memory tokens, uint256[] memory amounts) = s.pool.calcTokensForAmount(_tokens_bought); eth_sold = 0; // Buy and approve tokens for(uint256 i = 0; i < tokens.length; i ++) { eth_sold += _ethToToken(tokens[i], amounts[i]); IERC20(tokens[i]).approve(address(s.pool), uint256(-1)); } // Calculate amount of eth sold eth_sold = msg.value - address(this).balance; // Send back excess eth msg.sender.transfer(address(this).balance); // Join pool s.pool.joinPool(_tokens_bought); // Send pool tokens to receiver s.pool.transfer(_recipient, s.pool.balanceOf(address(this))); return eth_sold; } function ethToTokenSwapOutput(uint256 _tokens_bought, uint256 _deadline) external payable returns (uint256 eth_sold) { return ethToTokenTransferOutput(_tokens_bought, _deadline, msg.sender); } function _ethToToken(address _token, uint256 _tokens_bought) internal virtual returns (uint256) { uprs storage s = luprs(); IUniswapExchange exchange = IUniswapExchange(s.uniswapFactory.getExchange(_token)); return exchange.ethToTokenSwapOutput{value: address(this).balance}(_tokens_bought, uint256(-1)); } function getEthToTokenOutputPrice(uint256 _tokens_bought) external view virtual returns (uint256 eth_sold) { uprs storage s = luprs(); (address[] memory tokens, uint256[] memory amounts) = s.pool.calcTokensForAmount(_tokens_bought); eth_sold = 0; for(uint256 i = 0; i < tokens.length; i ++) { IUniswapExchange exchange = IUniswapExchange(s.uniswapFactory.getExchange(tokens[i])); eth_sold += exchange.getEthToTokenOutputPrice(amounts[i]); } return eth_sold; } function tokenToEthTransferInput(uint256 _tokens_sold, uint256 _min_eth, uint256 _deadline, address _recipient) public returns (uint256 eth_bought) { uprs storage s = luprs(); require(_deadline >= block.timestamp); require(s.pool.transferFrom(msg.sender, address(this), _tokens_sold), "PUniswapPoolRecipe.tokenToEthTransferInput: transferFrom failed"); s.pool.exitPool(_tokens_sold); address[] memory tokens = s.pool.getTokens(); uint256 ethAmount = 0; for(uint256 i = 0; i < tokens.length; i ++) { IERC20 token = IERC20(tokens[i]); uint256 balance = token.balanceOf(address(this)); // Exchange for ETH ethAmount += _tokenToEth(token, balance, _recipient); } require(ethAmount > _min_eth, "PUniswapPoolRecipe.tokenToEthTransferInput: not enough ETH"); return ethAmount; } function tokenToEthSwapInput(uint256 _tokens_sold, uint256 _min_eth, uint256 _deadline) external returns (uint256 eth_bought) { return tokenToEthTransferInput(_tokens_sold, _min_eth, _deadline, msg.sender); } function _tokenToEth(IERC20 _token, uint256 _tokens_sold, address _recipient) internal virtual returns (uint256 eth_bought) { uprs storage s = luprs(); IUniswapExchange exchange = IUniswapExchange(s.uniswapFactory.getExchange(address(_token))); _token.approve(address(exchange), _tokens_sold); // Exchange for ETH return exchange.tokenToEthTransferInput(_tokens_sold, 1, uint256(-1), _recipient); } function getTokenToEthInputPrice(uint256 _tokens_sold) external view virtual returns (uint256 eth_bought) { uprs storage s = luprs(); (address[] memory tokens, uint256[] memory amounts) = s.pool.calcTokensForAmount(_tokens_sold); eth_bought = 0; for(uint256 i = 0; i < tokens.length; i ++) { IUniswapExchange exchange = IUniswapExchange(s.uniswapFactory.getExchange(address(tokens[i]))); eth_bought += exchange.getTokenToEthInputPrice(amounts[i]); } return eth_bought; } function pool() external view returns (address) { return address(luprs().pool); } receive() external payable { } // Load uniswap pool recipe function luprs() internal pure returns (uprs storage s) { bytes32 loc = uprSlot; assembly { s_slot := loc } } } // File contracts/interfaces/IKyberNetwork.sol pragma solidity ^0.6.4; interface IKyberNetwork { function trade( address src, uint srcAmount, address dest, address payable destAddress, uint maxDestAmount, uint minConversionRate, address walletId ) external payable returns(uint256); } // File contracts/recipes/PUniswapKyberPoolRecipe.sol pragma solidity ^0.6.4; contract PUniswapKyberPoolRecipe is PUniswapPoolRecipe, Ownable { bytes32 constant public ukprSlot = keccak256("PUniswapKyberPoolRecipe.storage.location"); // Uniswap pool recipe struct struct ukprs { mapping(address => bool) swapOnKyber; IKyberNetwork kyber; address feeReceiver; } address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; function init(address, address) public override { require(false, "not enabled"); } // Use seperate init function function initUK(address _pool, address _uniswapFactory, address _kyber, address[] memory _swapOnKyber, address _feeReciever) public { // UnsiwapRecipe enforces that init can only be called once ukprs storage s = lukprs(); PUniswapPoolRecipe.init(_pool, _uniswapFactory); s.kyber = IKyberNetwork(_kyber); s.feeReceiver = _feeReciever; _setOwner(msg.sender); for(uint256 i = 0; i < _swapOnKyber.length; i ++) { s.swapOnKyber[_swapOnKyber[i]] = true; } } function setKyberSwap(address _token, bool _value) external onlyOwner { ukprs storage s = lukprs(); s.swapOnKyber[_token] = _value; } function _ethToToken(address _token, uint256 _tokens_bought) internal override returns (uint256) { ukprs storage s = lukprs(); if(!s.swapOnKyber[_token]) { return super._ethToToken(_token, _tokens_bought); } uint256 ethBefore = address(this).balance; s.kyber.trade{value: address(this).balance}(ETH, address(this).balance, _token, address(this), _tokens_bought, 1, s.feeReceiver); uint256 ethAfter = address(this).balance; // return amount of ETH spend return ethBefore - ethAfter; } function _tokenToEth(IERC20 _token, uint256 _tokens_sold, address _recipient) internal override returns (uint256 eth_bought) { ukprs storage s = lukprs(); if(!s.swapOnKyber[address(_token)]) { return super._tokenToEth(_token, _tokens_sold, _recipient); } uint256 ethBefore = address(this).balance; _token.approve(address(s.kyber), uint256(-1)); s.kyber.trade(address(_token), _tokens_sold, ETH, address(this), uint256(-1), 1, s.feeReceiver); uint256 ethAfter = address(this).balance; // return amount of ETH received return ethAfter - ethBefore; } // Load uniswap pool recipe function lukprs() internal pure returns (ukprs storage s) { bytes32 loc = ukprSlot; assembly { s_slot := loc } } } // File contracts/test/TestReentryProtection.sol pragma solidity ^0.6.4; contract TestReentryProtection is ReentryProtection { // This should fail function test() external noReentry { reenter(); } function reenter() public noReentry { // Do nothing } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"_value","type":"address"}],"name":"addressToBytes32","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_value","type":"bytes32"}],"name":"bytes32ToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_value","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauzer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProxyOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"readAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"readBool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"readString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renouncePauzer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_value","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPauzer","type":"address"}],"name":"setPauzer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setProxyOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"}],"name":"storageRead","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_value","type":"string"}],"name":"stringToBytes32","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061005460405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001203361009d60201b60201c565b61009860405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001203361009d60201b60201c565b6100d5565b6100c1826100b3836001600160e01b036100c516565b6001600160e01b036100d116565b5050565b6001600160a01b031690565b9055565b610d2d806100e46000396000f3fe6080604052600436106100fe5760003560e01c806382c947b711610095578063aaf10f4211610064578063aaf10f4214610377578063bb15ac8e1461038c578063caaee91c146103b6578063cfb51928146103e9578063d784d4261461049c576100fe565b806382c947b7146102bd5780638f4edfe2146102f05780639201de55146103235780639d84ae691461034d576100fe565b806337a440e6116100d157806337a440e6146102195780634bde4b2e146102555780635ced058e1461026a5780636805b84b14610294576100fe565b806316c38b3c1461010857806317b857dd146101345780631ab7710d146101495780631bc289601461017a575b6101066104cf565b005b34801561011457600080fd5b506101066004803603602081101561012b57600080fd5b50351515610552565b34801561014057600080fd5b5061010661061f565b34801561015557600080fd5b5061015e6106ea565b604080516001600160a01b039092168252519081900360200190f35b34801561018657600080fd5b506101a46004803603602081101561019d57600080fd5b503561072d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101de5781810151838201526020016101c6565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561022557600080fd5b506102436004803603602081101561023c57600080fd5b5035610748565b60408051918252519081900360200190f35b34801561026157600080fd5b5061015e61074c565b34801561027657600080fd5b5061015e6004803603602081101561028d57600080fd5b503561078b565b3480156102a057600080fd5b506102a961078e565b604080519115158252519081900360200190f35b3480156102c957600080fd5b50610243600480360360208110156102e057600080fd5b50356001600160a01b03166107cd565b3480156102fc57600080fd5b506101066004803603602081101561031357600080fd5b50356001600160a01b03166107d9565b34801561032f57600080fd5b506101a46004803603602081101561034657600080fd5b50356108a2565b34801561035957600080fd5b5061015e6004803603602081101561037057600080fd5b50356109a7565b34801561038357600080fd5b5061015e6109ba565b34801561039857600080fd5b506102a9600480360360208110156103af57600080fd5b5035610a01565b3480156103c257600080fd5b50610106600480360360208110156103d957600080fd5b50356001600160a01b0316610a15565b3480156103f557600080fd5b506102436004803603602081101561040c57600080fd5b81019060208101813564010000000081111561042757600080fd5b82018360208201111561043957600080fd5b8035906020019184600183028401116401000000008311171561045b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610add945050505050565b3480156104a857600080fd5b50610106600480360360208110156104bf57600080fd5b50356001600160a01b0316610afb565b61050c60405160200180806a14105554d15117d4d313d560aa1b815250600b01905060405160208183030381529060405280519060200120610a01565b156105485760405162461bcd60e51b815260040180806020018281038252602c815260200180610ccc602c913960400191505060405180910390fd5b610550610bcc565b565b61058f60405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146105de5760405162461bcd60e51b8152600401808060200182810382526030815260200180610c716030913960400191505060405180910390fd5b61061c60405160200180806a14105554d15117d4d313d560aa1b815250600b0190506040516020818303038152906040528051906020012082610c3a565b50565b61065c60405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146106ab5760405162461bcd60e51b8152600401808060200182810382526030815260200180610c716030913960400191505060405180910390fd5b61055060405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206000610c5f565b600061072860405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b905090565b606061074061073b83610748565b6108a2565b90505b919050565b5490565b600061072860405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b90565b600061072860405160200180806a14105554d15117d4d313d560aa1b815250600b01905060405160208183030381529060405280519060200120610a01565b6001600160a01b031690565b61081560405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146108645760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180806a14105556915497d4d313d560aa1b815250600b0190506040516020818303038152906040528051906020012082610c5f565b6040805160208082528183019092526060918291906020820181803683370190505090506000805b6020811015610920576008810260020a85026001600160f81b031981161561091757808484815181106108f957fe5b60200101906001600160f81b031916908160001a9053506001909201915b506001016108ca565b506060816040519080825280601f01601f19166020018201604052801561094e576020820181803683370190505b50905060005b8281101561099e5783818151811061096857fe5b602001015160f81c60f81b82828151811061097f57fe5b60200101906001600160f81b031916908160001a905350600101610954565b50949350505050565b60006107406109b583610748565b61078b565b600061072860405160200180807212535413115351539510551253d397d4d313d5606a1b8152506013019050604051602081830303815290604052805190602001206109a7565b60006001610a0e83610748565b1492915050565b610a5160405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b031614610aa05760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180806913d5d3915497d4d313d560b21b815250600a0190506040516020818303038152906040528051906020012082610c5f565b80516000908290610af2575060009050610743565b50506020015190565b610b3760405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b031614610b865760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180807212535413115351539510551253d397d4d313d5606a1b81525060130190506040516020818303038152906040528051906020012082610c5f565b6000610c1360405160200180807212535413115351539510551253d397d4d313d5606a1b8152506013019050604051602081830303815290604052805190602001206109a7565b905060405136600082376000803683855af43d806000843e818015610c36578184f35b8184fd5b8015610c5057610c4b826001610c6c565b610c5b565b610c5b826000610c6c565b5050565b610c5b82610c6c836107cd565b905556fe5050726f78795061757361626c652e6f6e6c795061757a65723a206d73672073656e646572206e6f74207061757a65725050726f78792e6f6e6c7950726f78794f776e65723a206d73672073656e646572206e6f74206f776e65725050726f78795061757361626c652e6e6f745061757365643a20636f6e747261637420697320706175736564a2646970667358221220402a3349b51886149d11d3fe7ed7ff4d98a6c6375ecb098e332019cc656fb6d864736f6c63430006040033
Deployed Bytecode
0x6080604052600436106100fe5760003560e01c806382c947b711610095578063aaf10f4211610064578063aaf10f4214610377578063bb15ac8e1461038c578063caaee91c146103b6578063cfb51928146103e9578063d784d4261461049c576100fe565b806382c947b7146102bd5780638f4edfe2146102f05780639201de55146103235780639d84ae691461034d576100fe565b806337a440e6116100d157806337a440e6146102195780634bde4b2e146102555780635ced058e1461026a5780636805b84b14610294576100fe565b806316c38b3c1461010857806317b857dd146101345780631ab7710d146101495780631bc289601461017a575b6101066104cf565b005b34801561011457600080fd5b506101066004803603602081101561012b57600080fd5b50351515610552565b34801561014057600080fd5b5061010661061f565b34801561015557600080fd5b5061015e6106ea565b604080516001600160a01b039092168252519081900360200190f35b34801561018657600080fd5b506101a46004803603602081101561019d57600080fd5b503561072d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101de5781810151838201526020016101c6565b50505050905090810190601f16801561020b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561022557600080fd5b506102436004803603602081101561023c57600080fd5b5035610748565b60408051918252519081900360200190f35b34801561026157600080fd5b5061015e61074c565b34801561027657600080fd5b5061015e6004803603602081101561028d57600080fd5b503561078b565b3480156102a057600080fd5b506102a961078e565b604080519115158252519081900360200190f35b3480156102c957600080fd5b50610243600480360360208110156102e057600080fd5b50356001600160a01b03166107cd565b3480156102fc57600080fd5b506101066004803603602081101561031357600080fd5b50356001600160a01b03166107d9565b34801561032f57600080fd5b506101a46004803603602081101561034657600080fd5b50356108a2565b34801561035957600080fd5b5061015e6004803603602081101561037057600080fd5b50356109a7565b34801561038357600080fd5b5061015e6109ba565b34801561039857600080fd5b506102a9600480360360208110156103af57600080fd5b5035610a01565b3480156103c257600080fd5b50610106600480360360208110156103d957600080fd5b50356001600160a01b0316610a15565b3480156103f557600080fd5b506102436004803603602081101561040c57600080fd5b81019060208101813564010000000081111561042757600080fd5b82018360208201111561043957600080fd5b8035906020019184600183028401116401000000008311171561045b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610add945050505050565b3480156104a857600080fd5b50610106600480360360208110156104bf57600080fd5b50356001600160a01b0316610afb565b61050c60405160200180806a14105554d15117d4d313d560aa1b815250600b01905060405160208183030381529060405280519060200120610a01565b156105485760405162461bcd60e51b815260040180806020018281038252602c815260200180610ccc602c913960400191505060405180910390fd5b610550610bcc565b565b61058f60405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146105de5760405162461bcd60e51b8152600401808060200182810382526030815260200180610c716030913960400191505060405180910390fd5b61061c60405160200180806a14105554d15117d4d313d560aa1b815250600b0190506040516020818303038152906040528051906020012082610c3a565b50565b61065c60405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146106ab5760405162461bcd60e51b8152600401808060200182810382526030815260200180610c716030913960400191505060405180910390fd5b61055060405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206000610c5f565b600061072860405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b905090565b606061074061073b83610748565b6108a2565b90505b919050565b5490565b600061072860405160200180806a14105556915497d4d313d560aa1b815250600b019050604051602081830303815290604052805190602001206109a7565b90565b600061072860405160200180806a14105554d15117d4d313d560aa1b815250600b01905060405160208183030381529060405280519060200120610a01565b6001600160a01b031690565b61081560405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b0316146108645760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180806a14105556915497d4d313d560aa1b815250600b0190506040516020818303038152906040528051906020012082610c5f565b6040805160208082528183019092526060918291906020820181803683370190505090506000805b6020811015610920576008810260020a85026001600160f81b031981161561091757808484815181106108f957fe5b60200101906001600160f81b031916908160001a9053506001909201915b506001016108ca565b506060816040519080825280601f01601f19166020018201604052801561094e576020820181803683370190505b50905060005b8281101561099e5783818151811061096857fe5b602001015160f81c60f81b82828151811061097f57fe5b60200101906001600160f81b031916908160001a905350600101610954565b50949350505050565b60006107406109b583610748565b61078b565b600061072860405160200180807212535413115351539510551253d397d4d313d5606a1b8152506013019050604051602081830303815290604052805190602001206109a7565b60006001610a0e83610748565b1492915050565b610a5160405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b031614610aa05760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180806913d5d3915497d4d313d560b21b815250600a0190506040516020818303038152906040528051906020012082610c5f565b80516000908290610af2575060009050610743565b50506020015190565b610b3760405160200180806913d5d3915497d4d313d560b21b815250600a019050604051602081830303815290604052805190602001206109a7565b6001600160a01b0316336001600160a01b031614610b865760405162461bcd60e51b815260040180806020018281038252602b815260200180610ca1602b913960400191505060405180910390fd5b61061c60405160200180807212535413115351539510551253d397d4d313d5606a1b81525060130190506040516020818303038152906040528051906020012082610c5f565b6000610c1360405160200180807212535413115351539510551253d397d4d313d5606a1b8152506013019050604051602081830303815290604052805190602001206109a7565b905060405136600082376000803683855af43d806000843e818015610c36578184f35b8184fd5b8015610c5057610c4b826001610c6c565b610c5b565b610c5b826000610c6c565b5050565b610c5b82610c6c836107cd565b905556fe5050726f78795061757361626c652e6f6e6c795061757a65723a206d73672073656e646572206e6f74207061757a65725050726f78792e6f6e6c7950726f78794f776e65723a206d73672073656e646572206e6f74206f776e65725050726f78795061757361626c652e6e6f745061757365643a20636f6e747261637420697320706175736564a2646970667358221220402a3349b51886149d11d3fe7ed7ff4d98a6c6375ecb098e332019cc656fb6d864736f6c63430006040033
Deployed Bytecode Sourcemap
4708:1253:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4050:18;:16;:18::i;:::-;4708:1253;5744:97;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5744:97:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5744:97:0;;;;:::i;5535:98::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5535:98:0;;;:::i;3487:103::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3487:103:0;;;:::i;:::-;;;;-1:-1:-1;;;;;3487:103:0;;;;;;;;;;;;;;255:129;;5:9:-1;2:2;;;27:1;24;17:12;2:2;255:129:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;255:129:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;255:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1141:248;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1141:248:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1141:248:0;;:::i;:::-;;;;;;;;;;;;;;;;5304:101;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5304:101:0;;;:::i;1711:130::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1711:130:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1711:130:0;;:::i;5641:95::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5641:95:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;1849:121;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1849:121:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1849:121:0;-1:-1:-1;;;;;1849:121:0;;:::i;5413:114::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5413:114:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5413:114:0;-1:-1:-1;;;;;5413:114:0;;:::i;2300:636::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2300:636:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2300:636:0;;:::i;880:125::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;880:125:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;880:125:0;;:::i;3722:117::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3722:117:0;;;:::i;524:124::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;524:124:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;524:124:0;;:::i;3598:116::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3598:116:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3598:116:0;-1:-1:-1;;;;;3598:116:0;;:::i;1978:314::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1978:314:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;1978:314:0;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;1978:314:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;1978:314:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;1978:314:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;1978:314:0;;-1:-1:-1;1978:314:0;;-1:-1:-1;;;;;1978:314:0:i;3847:147::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3847:147:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3847:147:0;-1:-1:-1;;;;;3847:147:0;;:::i;5849:107::-;5206:21;4792:31;;;;;;-1:-1:-1;;;4792:31:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4792:31:0;;;4782:42;;;;;;5206:8;:21::i;:::-;5205:22;5197:79;;;;-1:-1:-1;;;5197:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5924:24:::1;:22;:24::i;:::-;5849:107::o:0;5744:97::-;5060:24;4872:31;;;;;;-1:-1:-1;;;4872:31:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4872:31:0;;;4862:42;;;;;;5060:11;:24::i;:::-;-1:-1:-1;;;;;5046:38:0;:10;:38;5038:99;;;;-1:-1:-1;;;5038:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5805:28:::1;4792:31;;;;;;-1:-1:-1::0;;;4792:31:0::1;;::::0;::::1;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4792:31:0;;;4782:42;;;;;;5826:6;5805:7;:28::i;:::-;5744:97:::0;:::o;5535:98::-;5060:24;4872:31;;;;;;-1:-1:-1;;;4872:31:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4872:31:0;;;4862:42;;;;;;5060:11;:24::i;:::-;-1:-1:-1;;;;;5046:38:0;:10;:38;5038:99;;;;-1:-1:-1;;;5038:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5590:35:::1;4872:31;;;;;;-1:-1:-1::0;;;4872:31:0::1;;::::0;::::1;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4872:31:0;;;4862:42;;;;;;5622:1;5590:10;:35::i;3487:103::-:0;3533:7;3559:23;3206:30;;;;;;-1:-1:-1;;;3206:30:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3206:30:0;;;3196:41;;;;;;3559:11;:23::i;:::-;3552:30;;3487:103;:::o;255:129::-;309:13;342:34;358:17;370:4;358:11;:17::i;:::-;342:15;:34::i;:::-;335:41;;255:129;;;;:::o;1141:248::-;1337:11;;1141:248::o;5304:101::-;5346:7;5373:24;4872:31;;;;;;-1:-1:-1;;;4872:31:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4872:31:0;;;4862:42;;;;;;5373:11;:24::i;1711:130::-;1824:6;1711:130::o;5641:95::-;5683:4;5707:21;4792:31;;;;;;-1:-1:-1;;;4792:31:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4792:31:0;;;4782:42;;;;;;5707:8;:21::i;1849:121::-;-1:-1:-1;;;;;1946:15:0;;1849:121::o;5413:114::-;3305:23;3206:30;;;;;;-1:-1:-1;;;3206:30:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3206:30:0;;;3196:41;;;;;;3305:11;:23::i;:::-;-1:-1:-1;;;;;3291:37:0;:10;:37;3283:93;;;;-1:-1:-1;;;3283:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5484:35:::1;4872:31;;;;;;-1:-1:-1::0;;;4872:31:0::1;;::::0;::::1;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4872:31:0;;;4862:42;;;;;;5508:10;5484;:35::i;2300:636::-:0;2415:13;;;2425:2;2415:13;;;;;;;;;2362;;;;2415;;;;21:6:-1;;108:14;2415:13:0;87:42:-1;143:17;;-1:-1;;2388:40:0;-1:-1:-1;2439:14:0;;2468:237;2492:2;2488:1;:6;2468:237;;;2562:1;:5;;2556:1;:12;2541:27;;-1:-1:-1;;;;;;2589:9:0;;;2585:109;;2644:4;2619:11;2631:9;2619:22;;;;;;;;-1:-1:-1;;;;;;2619:29:0;;;;;;;;;:22;;;:29;-1:-1:-1;2667:11:0;;;;;2585:109;-1:-1:-1;2496:3:0;;2468:237;;;;2715:31;2759:9;2749:20;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;108:14;2749:20:0;87:42:-1;143:17;;-1:-1;2749:20:0;-1:-1:-1;2715:54:0;-1:-1:-1;2785:9:0;2780:105;2804:9;2800:1;:13;2780:105;;;2859:11;2871:1;2859:14;;;;;;;;;;;;;;;;2835:18;2854:1;2835:21;;;;;;;;-1:-1:-1;;;;;;2835:38:0;;;;;;;;;:21;;;:38;-1:-1:-1;2815:3:0;;2780:105;;;-1:-1:-1;2909:18:0;2300:636;-1:-1:-1;;;;2300:636:0:o;880:125::-;935:7;962:35;979:17;991:4;979:11;:17::i;:::-;962:16;:35::i;3722:117::-;3772:7;3799:32;3119:39;;;;;;-1:-1:-1;;;3119:39:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3119:39:0;;;3109:50;;;;;;3799:11;:32::i;524:124::-;576:4;637:1;600:17;612:4;600:11;:17::i;:::-;:40;;524:124;-1:-1:-1;;524:124:0:o;3598:116::-;3305:23;3206:30;;;;;;-1:-1:-1;;;3206:30:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3206:30:0;;;3196:41;;;;;;3305:11;:23::i;:::-;-1:-1:-1;;;;;3291:37:0;:10;:37;3283:93;;;;-1:-1:-1;;;3283:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3673:33:::1;3206:30;;;;;;-1:-1:-1::0;;;3206:30:0::1;;::::0;::::1;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3206:30:0;;;3196:41;;;;;;3696:9;3673:10;:33::i;1978:314::-:0;2136:26;;2046:14;;2114:6;;2132:74;;-1:-1:-1;2191:3:0;;-1:-1:-1;2184:10:0;;2132:74;-1:-1:-1;;2270:2:0;2258:15;2252:22;;2227:58::o;3847:147::-;3305:23;3206:30;;;;;;-1:-1:-1;;;3206:30:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3206:30:0;;;3196:41;;;;;;3305:11;:23::i;:::-;-1:-1:-1;;;;;3291:37:0;:10;:37;3283:93;;;;-1:-1:-1;;;3283:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3935:51:::1;3119:39;;;;;;-1:-1:-1::0;;;3119:39:0::1;;::::0;::::1;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3119:39:0;;;3109:50;;;;;;3967:18;3935:10;:51::i;4084:522::-:0;4140:20;4163:32;3119:39;;;;;;-1:-1:-1;;;3119:39:0;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3119:39:0;;;3109:50;;;;;;4163:11;:32::i;:::-;4140:55;;4247:4;4241:11;4287:14;4284:1;4279:3;4266:36;4388:1;4385;4369:14;4364:3;4350:12;4343:5;4330:60;4416:16;4469:4;4466:1;4461:3;4446:28;4497:6;4517:28;;;;4581:4;4576:3;4569:17;4517:28;4538:4;4533:3;4526:17;656:216;723:6;720:145;;;746:37;757:4;779:1;746:10;:37::i;:::-;720:145;;;816:37;827:4;849:1;816:10;:37::i;:::-;656:216;;:::o;1013:120::-;1083:42;1094:4;1100:24;1117:6;1100:16;:24::i;:::-;1648:37;;1633:63::o
Swarm Source
ipfs://402a3349b51886149d11d3fe7ed7ff4d98a6c6375ecb098e332019cc656fb6d8
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.