Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"PayPool.sol": {
"content": "// SPDX-License-Identifier: MIT\r
\r
pragma solidity 0.8.12;\r
import "./interfaces/IPayPool.sol";\r
contract PayPool is IPayPool {\r
\r
ILendingPool public constant aaveLendingPool=ILendingPool(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);\r
ILendingPool public constant lidoLendingPool=ILendingPool(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);\r
ILendingPool public constant ethenaLendingPool=ILendingPool(0x9D39A5DE30e57443BfF2A8307A4256c8797A3497);\r
ILidoWithdrawalQueueERC721 public constant lidoWithrawPool=ILidoWithdrawalQueueERC721(0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1);\r
\r
ICommonConfigs public constant commonConfigs=ICommonConfigs(0x3E428648C8549eC5a50b12156f42BB08182545d5);\r
\r
address public constant usdeToken=0x4c9EDD5852cd905f086C759E8383e09bff1E68B3;\r
address public constant susdeToken=0x9D39A5DE30e57443BfF2A8307A4256c8797A3497;\r
mapping(uint => mapping(address => uint)) public lendingAmount;\r
mapping(uint => uint) public lidoRequestAmount;\r
mapping(address => uint) public lidoTotalAmount;\r
mapping(address => uint) public lidoRemainAmount;\r
address private _owner;\r
\r
modifier onlyOwner() {\r
if (_owner !=msg.sender) {\r
revert OwnableUnauthorizedAccount(msg.sender);\r
}\r
_;\r
}\r
uint initStatus;\r
function initOwner()external{\r
if(initStatus==0){\r
initStatus=1;\r
_owner=msg.sender;\r
}\r
}\r
constructor() {\r
initStatus=1;\r
_owner=msg.sender;\r
}\r
receive() external payable {}\r
fallback() external payable {}\r
\r
function getAssetBlance(address token) internal view returns (uint112 tokenBal) {\r
assembly {\r
let emptyPointer := mload(0x40)\r
mstore(emptyPointer, 0x70a0823100000000000000000000000000000000000000000000000000000000)\r
mstore(add(emptyPointer, 0x04), address())\r
let success := staticcall(gas(), token, emptyPointer, 0x24, emptyPointer, 0x40)\r
if success {\r
tokenBal := mload(emptyPointer)\r
}\r
}\r
}\r
function _transfer(address token,address to,uint256 amount) internal {\r
assembly {\r
let emptyPointer := mload(0x40)\r
mstore(\r
emptyPointer,\r
0xa9059cbb00000000000000000000000000000000000000000000000000000000\r
)\r
mstore(add(emptyPointer, 0x04),to)\r
mstore(add(emptyPointer, 0x24), amount)\r
let failed := iszero(\r
call(gas(), token, 0, emptyPointer, 0x44, 0, 0)\r
)\r
if failed {\r
returndatacopy(0, 0, returndatasize())\r
revert(0, returndatasize())\r
}\r
}\r
}\r
\r
function tokenApprove(address token,address spender, uint256 amount) internal {\r
assembly {\r
let emptyPointer := mload(0x40)\r
mstore(\r
emptyPointer,\r
0x095ea7b300000000000000000000000000000000000000000000000000000000\r
)\r
mstore(add(emptyPointer, 0x04), spender)\r
mstore(add(emptyPointer, 0x24), amount)\r
if iszero(call(gas(), token, 0, emptyPointer, 0x44, 0, 0)) {\r
returndatacopy(0, 0, returndatasize())\r
revert(0, returndatasize())\r
}\r
}\r
}\r
function getFee(uint256 _amount,uint rewardFeeRate)internal pure returns(uint fee){\r
fee=_amount*rewardFeeRate/1e4;\r
}\r
function getColdPool() internal view returns(address coldPool) {\r
(bool success, bytes memory data) = msg.sender.staticcall(\r
abi.encodeWithSelector(0xb5e1e3bf)//abi.encodeWithSelector(getColdPool.selector)\r
);\r
if(success){\r
coldPool=abi.decode(data, (address));\r
}\r
}\r
function depositByAave(address token) external onlyOwner returns (uint assets){\r
assets=getAssetBlance(token);\r
tokenApprove(token,address(aaveLendingPool), assets);\r
aaveLendingPool.supply(token, assets, address(this), 0);\r
tokenApprove(token,address(aaveLendingPool), 0);\r
lendingAmount[1][token]+=assets;\r
emit DepositByAave(token,assets);\r
}\r
function withdrawByAave(address token,uint assets) external onlyOwner returns(uint amount,uint256 reward){\r
uint totalLendingAmount=lendingAmount[1][token];\r
if(totalLendingAmount>0){\r
aaveLendingPool.withdraw(token, type(uint256).max, address(this));\r
(uint rewardFeeRate,address feeTo)=commonConfigs.getFeeInfo(IMultiSigCold(msg.sender));\r
amount=getAssetBlance(token);\r
uint fee;\r
if(amount>totalLendingAmount+1000){\r
reward=amount-totalLendingAmount;\r
fee=getFee(reward,rewardFeeRate);\r
_transfer(token,feeTo,fee);\r
}\r
if(assets>=amount-fee){\r
lendingAmount[1][token]=0;\r
assets=getAssetBlance(token);\r
_transfer(token,getColdPool(),assets);\r
}else{\r
_transfer(token,getColdPool(),assets);\r
totalLendingAmount=getAssetBlance(token);\r
tokenApprove(token,address(aaveLendingPool), totalLendingAmount);\r
aaveLendingPool.supply(token, totalLendingAmount, address(this), 0);\r
tokenApprove(token,address(aaveLendingPool), 0);\r
lendingAmount[1][token]=totalLendingAmount;\r
}\r
emit WithdrawByAave(token,assets,amount,reward);\r
}\r
}\r
function depositByLido(address token) external onlyOwner returns (uint assets){\r
if(token==address(0)){\r
assets=address(this).balance;\r
}else{\r
assets=getAssetBlance(token);\r
IWETH(token).withdraw(assets);\r
}\r
(,address feeTo)=commonConfigs.getFeeInfo(IMultiSigCold(msg.sender));\r
uint amount=lidoLendingPool.submit{value: assets}(feeTo);\r
lidoTotalAmount[token]+=amount;\r
lidoRemainAmount[token]+=amount;\r
lendingAmount[2][token]+=assets;\r
emit DepositByLido(token,assets);\r
if(address(lidoLendingPool)==address(0)){\r
revert();\r
}\r
}\r
\r
// 请求提现\r
function lidoRequestWithdrawals(address token,uint256[] calldata _amounts)external onlyOwner returns (uint256[] memory requestIds){\r
uint assets;\r
for (uint256 i; i < _amounts.length; ++i) {\r
assets += _amounts[i];\r
}\r
lidoRemainAmount[token]-=assets;\r
tokenApprove(address(lidoLendingPool),address(lidoWithrawPool), assets);\r
\r
requestIds=lidoWithrawPool.requestWithdrawals(_amounts, address(this));\r
tokenApprove(address(lidoLendingPool),address(lidoWithrawPool), 0);\r
for (uint256 i; i < _amounts.length; ++i) {\r
lidoRequestAmount[requestIds[i]] = _amounts[i];\r
}\r
}\r
function withdrawByLido(uint256[] memory requestIds,address token,uint assets) external onlyOwner returns(uint amount,uint256 reward){\r
uint totalLendingAmount=lendingAmount[2][token];\r
if(totalLendingAmount>0){\r
uint totalEAmount;\r
for (uint256 i; i < requestIds.length; ++i) {\r
totalEAmount+= lidoRequestAmount[requestIds[i]];\r
delete lidoRequestAmount[requestIds[i]];\r
}\r
totalLendingAmount=totalLendingAmount*totalEAmount/lidoTotalAmount[token]+1;\r
lidoTotalAmount[token]-=totalEAmount;\r
uint256[] memory _hints = lidoWithrawPool.findCheckpointHints(requestIds, 1, lidoWithrawPool.getLastCheckpointIndex());\r
lidoWithrawPool.claimWithdrawals(requestIds, _hints);\r
(uint rewardFeeRate,address feeTo)=commonConfigs.getFeeInfo(IMultiSigCold(msg.sender));\r
amount=address(this).balance;\r
uint fee;\r
if(amount>totalLendingAmount+1000){\r
reward=amount-totalLendingAmount;\r
fee=getFee(reward,rewardFeeRate);\r
ethTransfer(feeTo,fee);\r
}\r
if(lendingAmount[2][token]>totalLendingAmount){\r
lendingAmount[2][token]-=totalLendingAmount;\r
}else{\r
lendingAmount[2][token]=0;\r
}\r
if(assets>=amount-fee){\r
assets=address(this).balance;\r
if(token==address(0)){\r
ethTransfer(getColdPool(),assets);\r
}else{\r
IWETH(token).deposit{value:assets}();\r
_transfer(token,getColdPool(),assets);\r
}\r
}else{\r
if(token==address(0)){\r
ethTransfer(getColdPool(),assets);\r
}else{\r
IWETH(token).deposit{value:assets}();\r
_transfer(token,getColdPool(),assets);\r
}\r
uint bal=address(this).balance;\r
uint _amount=lidoLendingPool.submit{value: bal}(feeTo);\r
lidoTotalAmount[token]+=_amount;\r
lidoRemainAmount[token]+=_amount;\r
lendingAmount[2][token]+=bal;\r
}\r
emit WithdrawByLido(token,assets,amount,reward);\r
}\r
}\r
\r
function depositByEthenaStakeUsde() external onlyOwner returns (uint assets){\r
assets=getAssetBlance(usdeToken);\r
tokenApprove(usdeToken,address(ethenaLendingPool), assets);\r
ethenaLendingPool.deposit(assets, address(this));\r
tokenApprove(usdeToken,address(ethenaLendingPool), 0);\r
lendingAmount[4][usdeToken]+=assets;\r
emit DepositByEthena(usdeToken,assets);\r
}\r
function cooldownSharesForEthenaStake() external onlyOwner returns (uint256 assets){\r
assets=ethenaLendingPool.cooldownShares(getAssetBlance(susdeToken));\r
}\r
function withdrawByEthenaStakeUsde(uint assets) external onlyOwner returns (uint amount,uint256 reward){\r
uint totalLendingAmount=lendingAmount[4][usdeToken];\r
if(totalLendingAmount>0){\r
amount=getAssetBlance(usdeToken);\r
uint24 cooldownDuration=ethenaLendingPool.cooldownDuration();\r
(uint104 cooldownEnd,uint152 underlyingAmount)=ethenaLendingPool.cooldowns(address(this));\r
if (underlyingAmount>0) {\r
if(block.timestamp >= cooldownEnd || cooldownDuration == 0){\r
ethenaLendingPool.unstake(address(this));\r
(uint rewardFeeRate,address feeTo)=commonConfigs.getFeeInfo(IMultiSigCold(msg.sender));\r
amount=getAssetBlance(usdeToken)-amount;\r
uint fee;\r
if(amount>totalLendingAmount+1000){\r
reward=amount-totalLendingAmount;\r
fee=getFee(reward,rewardFeeRate);\r
_transfer(usdeToken,feeTo,fee);\r
}\r
if(assets>=amount-fee){\r
lendingAmount[4][usdeToken]=0;\r
assets=getAssetBlance(usdeToken);\r
_transfer(usdeToken,getColdPool(),assets);\r
}else{\r
_transfer(usdeToken,getColdPool(),assets);\r
totalLendingAmount=getAssetBlance(usdeToken);\r
tokenApprove(usdeToken,address(ethenaLendingPool), totalLendingAmount);\r
ethenaLendingPool.deposit(totalLendingAmount, address(this));\r
tokenApprove(usdeToken,address(ethenaLendingPool), 0);\r
lendingAmount[4][usdeToken]=totalLendingAmount;\r
}\r
emit WithdrawByEthena(usdeToken,assets,amount,reward);\r
}else{\r
revert EthenaCooldownNotEnd(msg.sender);\r
}\r
}else{\r
revert EthenaCooldownNotStart(msg.sender);\r
}\r
}\r
}\r
function ethTransfer(address recipient, uint256 amount) internal {\r
bool failed=false;\r
assembly {\r
failed := iszero(call(gas(), recipient, amount, 0, 0, 0, 0))\r
}\r
if (failed) {\r
revert EthTransfer(recipient, amount);\r
}\r
}\r
\r
function EmergencyCall(\r
bytes calldata data,\r
uint callType,\r
address callAddr\r
) external onlyOwner returns(bool success,bytes memory returnData){\r
commonConfigs.checkEmergencyCall(data,callType,callAddr);\r
if(callType==100){\r
(success,returnData)=callAddr.call(data);\r
}else if(callType==200){\r
(success,returnData)=callAddr.delegatecall(data);\r
}\r
}\r
}"
},
"interfaces/IPayPool.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
import "./ILendingPool.sol";\r
import "./ICommonConfigs.sol";\r
import "./IWETH.sol";\r
interface IPayPool{\r
event DepositByAave(address token,uint assets);\r
event WithdrawByAave(address token,uint assets,uint amount,uint256 reward);\r
\r
event DepositByLido(address token,uint assets);\r
event WithdrawByLido(address token,uint assets,uint amount,uint256 reward);\r
\r
event DepositByEthena(address token,uint assets);\r
event WithdrawByEthena(address token,uint assets,uint amount,uint256 reward);\r
function aaveLendingPool() external pure returns (ILendingPool);\r
function lidoLendingPool() external pure returns (ILendingPool);\r
function ethenaLendingPool() external pure returns (ILendingPool);\r
function commonConfigs() external pure returns (ICommonConfigs);\r
function usdeToken() external pure returns (address);\r
function lendingAmount(uint _type,address _user) external view returns (uint);\r
\r
error OwnableUnauthorizedAccount(address account);\r
error EthTransfer(address recipient, uint256 amount);\r
error EthenaCooldownNotStart(address account);\r
error EthenaCooldownNotEnd(address account);\r
function initOwner()external;\r
\r
function depositByAave(address token) external returns (uint assets);\r
function withdrawByAave(address token,uint assets) external returns(uint amount,uint256 reward);\r
\r
function depositByLido(address token) external returns (uint assets);\r
function withdrawByLido(uint256[] memory requestIds,address token,uint assets)external returns(uint amount,uint256 reward);\r
// 请求提现\r
function lidoRequestWithdrawals(address token,uint256[] calldata _amounts)external returns (uint256[] memory requestIds);\r
\r
function depositByEthenaStakeUsde() external returns (uint assets);\r
function cooldownSharesForEthenaStake() external returns (uint256 assets);\r
function withdrawByEthenaStakeUsde(uint assets) external returns (uint amount,uint256 reward);\r
\r
function EmergencyCall(\r
bytes calldata data,\r
uint callType,\r
address callAddr\r
) external returns(bool success,bytes memory returnData);\r
\r
}\r
"
},
"interfaces/IWETH.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
interface IWETH {\r
function deposit() external payable;\r
function withdraw(uint256) external;\r
}"
},
"interfaces/ICommonConfigs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
import "./IMultiSigCold.sol";\r
interface ICommonConfigs{\r
struct FeeInfo{\r
address feeTo;\r
uint16 feeRate;\r
}\r
function getFeeInfo(IMultiSigCold user)external view returns(uint,address);\r
\r
function setSupportEmergencyCalls(uint callType,address callAddr,bytes4 methodId,bytes memory signatures) external ;\r
function setFeeRate(uint16 _feeRate,IMultiSigCold user,bytes memory signatures) external ;\r
function setFreeFeeRate(IMultiSigCold user,bytes memory signatures) external ;\r
function checkEmergencyCall(bytes memory data,uint callType,address callAddr)external view;\r
}"
},
"interfaces/ILendingPool.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
import "./ILidoWithdrawalQueueERC721.sol";\r
\r
interface ILendingPool {\r
function withdraw(\r
address asset,\r
uint256 amount,\r
address to\r
) external returns (uint256);\r
function supply(\r
address asset,\r
uint256 amount,\r
address onBehalfOf,\r
uint16 referralCode\r
) external;\r
\r
//ethena---start\r
function cooldownShares(uint256 shares) external returns (uint256 assets);\r
function unstake(address receiver) external;\r
function deposit(uint256 assets, address receiver) external returns (uint256 shares);\r
function cooldowns(address receiver) external view returns(uint104 cooldownEnd,uint152 underlyingAmount);\r
function cooldownDuration() external view returns(uint24);\r
//ethena---end\r
// 质押到指定模块\r
\r
function submit(address _referral) external payable returns (uint256);//ldo\r
\r
}\r
"
},
"interfaces/ILidoWithdrawalQueueERC721.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
interface ILidoWithdrawalQueueERC721{\r
// 请求提现\r
function requestWithdrawals(uint256[] calldata _amounts, address _owner)external returns (uint256[] memory requestIds);\r
// 领取提现\r
function claimWithdrawals(uint256[] calldata _requestIds, uint256[] calldata _hints) external;\r
//获取提款请求\r
function getWithdrawalRequests(address _owner)external view returns (uint256[] memory requestsIds);\r
\r
function findCheckpointHints(uint256[] calldata _requestIds,uint256 _firstIndex,uint256 _lastIndex) external view returns (uint256[] memory hintIds);\r
function getLastCheckpointIndex() external view returns (uint256);\r
\r
}"
},
"interfaces/IMultiSigCold.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
\r
import "./IMultiSigUtc.sol";\r
struct Merchant {\r
/// Set the storage balance ratio of each merchant's hot contract\r
uint256 hotCoinMaxRatio;\r
/// Fee payment ratio for each merchant\r
uint256 feeRate;\r
/// Each merchant balance funds limit time\r
uint256 balancedTime;\r
/// The minimum voting ratio for multiple signatures for each merchant is at least 50 and the maximum is 100\r
uint256 primAgentProfitPerc;\r
/// Hot contract storage pool address\r
address payable hotPool;\r
/// Cold contract storage pool address\r
address payable coldPool;\r
/// Agent’s multi-signature address\r
address multiSigAgentAddr;\r
}\r
\r
interface IMultiSigCold{\r
function initManagers(Merchant memory data,IMultiSigUtc _multiSigUtc,uint ratio,uint expirationTime,address[] memory _managers) external;\r
function initOwner() external;\r
event TransferCommissionLogs(address indexed token, uint256 indexed totalCommission,uint256 indexed primCommission,uint256 web3PayCommission,uint256 transBalHot);\r
}"
},
"interfaces/IMultiSigUtc.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1\r
pragma solidity 0.8.12;\r
\r
interface IMultiSigUtc{\r
function getManagerInfo()external view returns(uint managerNumber,uint expirationTime,address[] memory managers);\r
function getUtcFeeAddr() external view returns(address);\r
}\r
"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}
}}
Submitted on: 2025-11-07 12:07:36
Comments
Log in to comment.
No comments yet.