编译器
0.8.17+commit.8df45f5f
文件 1 的 9:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 9:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 3 的 9:IVault.sol
pragma solidity ^0.8.17;
struct Permit {
uint256 amount;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
interface IVault {
function WETH() external view returns (address);
receive() external payable;
function deposit() external payable;
function depositToMPC() external payable;
function depositTokens(address from, address token, uint256 amount) external;
function depositTokensToMPC(address from, address token, uint256 amount) external;
function depositTokensWithPermit(address from, address token, uint256 amount, Permit calldata permit) external;
function depositTokensToMPCWithPermit(address from, address token, uint256 amount, Permit calldata permit) external;
function withdraw(address payable to, uint256 amount) external;
function withdrawTokens(address to, address token, uint256 amount) external;
}
文件 4 的 9:IWETH.sol
pragma solidity ^0.8.17;
interface IWETH {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function balanceOf(address) external view returns (uint256);
function allowance(address, address) external view returns (uint256);
function deposit() external payable;
function withdraw(uint256) external;
function approve(address guy, uint256 wad) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(address src, address dst, uint256 amount) external returns (bool);
}
文件 5 的 9:MPCManageable.sol
pragma solidity ^0.8.17;
abstract contract MPCManageable {
event MPCUpdated(address indexed oldMPC, address indexed newMPC, uint256 effectiveTime);
uint256 public constant DELAY = 2 days;
address internal _oldMPC;
address internal _newMPC;
uint256 internal _newMPCEffectiveTime;
constructor(address _MPC) {
_updateMPC(_MPC, 0);
}
modifier onlyMPC() {
_checkMPC();
_;
}
function mpc() public view returns (address) {
if (block.timestamp >= _newMPCEffectiveTime) {
return _newMPC;
}
return _oldMPC;
}
function updateMPC(address newMPC) public onlyMPC {
_updateMPC(newMPC, DELAY);
}
function _updateMPC(address newMPC, uint256 delay) private {
require(newMPC != address(0), "MPCManageable: Nullable MPC");
_oldMPC = mpc();
_newMPC = newMPC;
_newMPCEffectiveTime = block.timestamp + delay;
emit MPCUpdated(_oldMPC, _newMPC, _newMPCEffectiveTime);
}
function _checkMPC() internal view {
require(msg.sender == mpc(), "MPCManageable: Non MPC");
}
}
文件 6 的 9:MPCOperable.sol
pragma solidity ^0.8.17;
import "./MPCManageable.sol";
abstract contract MPCOperable is MPCManageable {
event Initialized();
event OperatorAdded(address indexed operator, uint256 effectiveTime);
event OperatorRemoved(address indexed operator);
bool private _initialized;
mapping(address => uint256) public operators;
modifier onlyMPCOperable() {
_checkMPCOperable();
_;
}
constructor(address _MPC) MPCManageable(_MPC) {}
function initOperators(address[] memory _operators) public onlyMPC {
require(!_initialized, "MPCOperable: Already initialized");
require(_operators.length > 0, "MPCOperable: Empty operators");
_initialized = true;
for (uint256 i = 0; i < _operators.length; i++) {
_addOperator(_operators[i], 0);
}
emit Initialized();
}
function initialized() public view returns (bool) {
return _initialized;
}
function addOperator(address operator) public onlyMPC {
_addOperator(operator, DELAY);
}
function removeOperator(address operator) public onlyMPC {
require(operators[operator] != 0, "MPCOperable: Operator doesn't exist");
delete operators[operator];
emit OperatorRemoved(operator);
}
function _addOperator(address operator, uint256 delay) private {
require(operator != address(0x0), "MPCOperable: Nullable operator");
require(operators[operator] == 0, "MPCOperable: Operator exists");
operators[operator] = block.timestamp + delay;
emit OperatorAdded(operator, operators[operator]);
}
function _checkMPCOperable() internal view {
require(
(operators[msg.sender] > 0 && block.timestamp >= operators[msg.sender]) || msg.sender == mpc(),
"MPCOperable: Must be MPC or operator"
);
}
}
文件 7 的 9:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 8 的 9:Vault.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "./access/MPCOperable.sol";
import "./interfaces/IVault.sol";
import "./interfaces/IWETH.sol";
contract Vault is MPCOperable, IVault {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Permit;
address public immutable WETH;
constructor(address _WETH, address _MPC) MPCOperable(_MPC) {
WETH = _WETH;
}
receive() external payable {}
function deposit() external payable {}
function depositToMPC() external payable {
_withdraw(payable(mpc()), msg.value);
}
function depositTokens(address from, address token, uint256 amount) external onlyMPCOperable {
_depositTokens(from, token, amount);
}
function depositTokensToMPC(address from, address token, uint256 amount) external onlyMPCOperable {
_depositTokensToMPC(from, token, amount);
}
function depositTokensWithPermit(
address from,
address token,
uint256 amount,
Permit calldata permit
) external onlyMPCOperable {
IERC20Permit(token).permit(from, address(this), permit.amount, permit.deadline, permit.v, permit.r, permit.s);
_depositTokens(from, token, amount);
}
function depositTokensToMPCWithPermit(
address from,
address token,
uint256 amount,
Permit calldata permit
) external onlyMPCOperable {
IERC20Permit(token).permit(from, address(this), permit.amount, permit.deadline, permit.v, permit.r, permit.s);
_depositTokensToMPC(from, token, amount);
}
function withdraw(address payable to, uint256 amount) external onlyMPCOperable {
_withdraw(to, amount);
}
function withdrawTokens(address to, address token, uint256 amount) external onlyMPCOperable {
IERC20(token).safeTransfer(to, amount);
}
function _depositTokens(address from, address token, uint256 amount) internal {
IERC20(token).safeTransferFrom(from, address(this), amount);
if (token == WETH) {
IWETH(WETH).withdraw(amount);
}
}
function _depositTokensToMPC(address from, address token, uint256 amount) internal {
if (token == WETH) {
IERC20(token).safeTransferFrom(from, address(this), amount);
IWETH(WETH).withdraw(amount);
_withdraw(payable(mpc()), amount);
} else {
IERC20(token).safeTransferFrom(from, mpc(), amount);
}
}
function _withdraw(address payable to, uint256 amount) private {
(bool success, ) = to.call{value: amount}("");
require(success, "Vault: Sending ETH has been failed");
}
}
文件 9 的 9:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/Vault.sol": "Vault"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_MPC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldMPC","type":"address"},{"indexed":true,"internalType":"address","name":"newMPC","type":"address"},{"indexed":false,"internalType":"uint256","name":"effectiveTime","type":"uint256"}],"name":"MPCUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"effectiveTime","type":"uint256"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorRemoved","type":"event"},{"inputs":[],"name":"DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositToMPC","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokensToMPC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Permit","name":"permit","type":"tuple"}],"name":"depositTokensToMPCWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Permit","name":"permit","type":"tuple"}],"name":"depositTokensWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_operators","type":"address[]"}],"name":"initOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mpc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMPC","type":"address"}],"name":"updateMPC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]