false
true
0
PulseChain
Blockchain
Blocks
Blocks
Uncles
Forked Blocks (Reorgs)
Transactions
Confirmed
Pending
Verified contracts
Tokens
All
PLS
APIs
GraphQL
RPC
Eth RPC
Apps
PulseChain Beacon Explorer
PulseX
PulseChain Bridge
Become a Validator
PulseChain
Mainnets
PulseChain Mainnet
Testnets
Testnet V4
/
Search
/
Search
Connection Lost
New Solidity Smart Contract Verification
Contract Address
The 0x address supplied on contract creation.
Is Yul contract
No
Yes
Select Yes if you want to verify Yul contract.
Contract Name
Must match the name specified in the code. For example, in
contract MyContract {..}
MyContract
is the contract name.
Include nightly builds
No
Yes
Select yes if you want to show nightly builds.
Compiler
v0.8.34+commit.80d5c536
v0.8.33+commit.64118f21
v0.8.32+commit.ebbd65e5
v0.8.31+commit.fd3a2265
v0.8.31-pre.1+commit.b59566f6
v0.8.30+commit.73712a01
v0.8.29+commit.ab55807c
v0.8.28+commit.7893614a
v0.8.27+commit.40a35a09
v0.8.26+commit.8a97fa7a
v0.8.25+commit.b61c2a91
v0.8.24+commit.e11b9ed9
v0.8.23+commit.f704f362
v0.8.22+commit.4fc1097e
v0.8.21+commit.d9974bed
v0.8.20+commit.a1b79de6
v0.8.19+commit.7dd6d404
v0.8.18+commit.87f61d96
v0.8.17+commit.8df45f5f
v0.8.16+commit.07a7930e
v0.8.15+commit.e14f2714
v0.8.14+commit.80d49f37
v0.8.13+commit.abaa5c0e
v0.8.12+commit.f00d7308
v0.8.11+commit.d7f03943
v0.8.10+commit.fc410830
v0.8.9+commit.e5eed63a
v0.8.8+commit.dddeac2f
v0.8.7+commit.e28d00a7
v0.8.6+commit.11564f7e
v0.8.5+commit.a4f2e591
v0.8.4+commit.c7e474f2
v0.8.3+commit.8d00100c
v0.8.2+commit.661d1103
v0.8.1+commit.df193b15
v0.8.0+commit.c7dfd78e
v0.7.6+commit.7338295f
v0.7.5+commit.eb77ed08
v0.7.4+commit.3f05b770
v0.7.3+commit.9bfce1f6
v0.7.2+commit.51b20bc0
v0.7.1+commit.f4a555be
v0.7.0+commit.9e61f92b
v0.6.12+commit.27d51765
v0.6.11+commit.5ef660b1
v0.6.10+commit.00c0fcaf
v0.6.9+commit.3e3065ac
v0.6.8+commit.0bbfe453
v0.6.7+commit.b8d736ae
v0.6.6+commit.6c089d02
v0.6.5+commit.f956cc89
v0.6.4+commit.1dca32f3
v0.6.3+commit.8dda9521
v0.6.2+commit.bacdbe57
v0.6.1+commit.e6f7d5a4
v0.6.0+commit.26b70077
v0.5.17+commit.d19bba13
v0.5.16+commit.9c3226ce
v0.5.15+commit.6a57276f
v0.5.14+commit.01f1aaa4
v0.5.13+commit.5b0b510c
v0.5.12+commit.7709ece9
v0.5.11+commit.22be8592
v0.5.10+commit.5a6ea5b1
v0.5.9+commit.c68bc34e
v0.5.8+commit.23d335f2
v0.5.7+commit.6da8b019
v0.5.6+commit.b259423e
v0.5.5+commit.47a71e8f
v0.5.4+commit.9549d8ff
v0.5.3+commit.10d17f24
v0.5.2+commit.1df8f40c
v0.5.1+commit.c8a2cb62
v0.5.0+commit.1d4f565a
v0.4.26+commit.4563c3fc
v0.4.25+commit.59dbf8f1
v0.4.24+commit.e67f0147
v0.4.23+commit.124ca40d
v0.4.22+commit.4cb486ee
v0.4.21+commit.dfe3193c
v0.4.20+commit.3155dd80
v0.4.19+commit.c4cbbb05
v0.4.18+commit.9cf6e910
v0.4.17+commit.bdeb9e52
v0.4.16+commit.d7661dd9
v0.4.15+commit.8b45bddb
v0.4.14+commit.c2215d46
v0.4.13+commit.0fb4cb1a
v0.4.12+commit.194ff033
v0.4.11+commit.68ef5810
v0.4.10+commit.9e8cc01b
The compiler version is specified in
pragma solidity X.X.X
. Use the compiler version rather than the nightly build. If using the Solidity compiler, run
solc —version
to check.
EVM Version
homestead
tangerineWhistle
spuriousDragon
byzantium
constantinople
petersburg
istanbul
berlin
london
paris
shanghai
default
The EVM version the contract is written for. If the bytecode does not match the version, we try to verify using the latest EVM version.
EVM version details
.
Optimization
No
Yes
If you enabled optimization during compilation, select yes.
Optimization runs
Enter the Solidity Contract Code
/** *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/PProxyStorage.sol@v0.0.6 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/PProxy.sol@v0.0.6 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/PProxyPausable.sol@v0.0.6 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 } }
We recommend using flattened code. This is necessary if your code utilizes a library or inherits dependencies. Use the
POA solidity flattener or the
truffle flattener
.
Try to fetch constructor arguments automatically
No
Yes
ABI-encoded Constructor Arguments (if required by the contract)
Add arguments in
ABI hex encoded form
. Constructor arguments are written right to left, and will be found at the end of the input created bytecode. They may also be
parsed here.
Add Contract Libraries
Contract Libraries
Library 1 Name
A library name called in the .sol file. Multiple libraries (up to 10) may be added for each contract. Click the Add Library button to add an additional one.
Library 1 Address
The 0x library address. This can be found in the generated json file or Truffle output (if using truffle).
Library 2 Name
Library 2 Address
Library 3 Name
Library 3 Address
Library 4 Name
Library 4 Address
Library 5 Name
Library 5 Address
Library 6 Name
Library 6 Address
Library 7 Name
Library 7 Address
Library 8 Name
Library 8 Address
Library 9 Name
Library 9 Address
Library 10 Name
Library 10 Address
Add Library
Loading...
Verify & publish
Cancel
Ok
Ok
Ok
No
Yes