编译器
0.8.17+commit.8df45f5f
文件 1 的 10: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 的 10:Common.sol
pragma solidity ^0.8.4;
library Common {
function _validateAddress(address _addr) internal pure {
require(_addr != address(0), "Address cannot be zero");
}
function _isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
}
文件 3 的 10:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 4 的 10:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 5 的 10:IERC20.sol
pragma solidity ^0.8.4;
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender, address recipient, uint256 amount) external returns (bool);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
文件 6 的 10:IStarBaseApprove.sol
pragma solidity ^0.8.4;
interface IStarBaseApprove {
function claimTokens(address token, address who, address dest, uint160 amount) external;
function getStarBaseProxy() external view returns (address);
}
文件 7 的 10:IStarBaseApproveProxy.sol
pragma solidity ^0.8.4;
interface IStarBaseApproveProxy {
function claimTokens(address token, address who, address dest, uint160 amount) external;
}
文件 8 的 10:InitializableOwnable.sol
pragma solidity ^0.8.4;
contract InitializableOwnable {
address public _OWNER_;
address public _NEW_OWNER_;
bool internal _INITIALIZED_;
event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier notInitialized() {
require(!_INITIALIZED_, "StarBase_INITIALIZED");
_;
}
modifier onlyOwner() {
require(msg.sender == _OWNER_, "NOT_OWNER");
_;
}
function initOwner(address newOwner) public notInitialized {
_INITIALIZED_ = true;
_OWNER_ = newOwner;
}
function transferOwnership(address newOwner) public onlyOwner {
emit OwnershipTransferPrepared(_OWNER_, newOwner);
_NEW_OWNER_ = newOwner;
}
function claimOwnership() public {
require(msg.sender == _NEW_OWNER_, "INVALID_CLAIM");
emit OwnershipTransferred(_OWNER_, _NEW_OWNER_);
_OWNER_ = _NEW_OWNER_;
_NEW_OWNER_ = address(0);
}
}
文件 9 的 10:SafeERC20.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/utils/Address.sol";
import { IERC20 } from "../intf/IERC20.sol";
library SafeERC20 {
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 _callOptionalReturn(IERC20 token, bytes memory data) private {
require(Address.isContract(address(token)), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 10 的 10:StarBaseApprove.sol
pragma solidity ^0.8.4;
import { IERC20 } from "./intf/IERC20.sol";
import { SafeERC20 } from "./lib/SafeERC20.sol";
import { InitializableOwnable } from "./lib/InitializableOwnable.sol";
import { Common } from "./lib/Common.sol";
import { IStarBaseApproveProxy } from "./intf/IStarBaseApproveProxy.sol";
import { IStarBaseApprove } from "./intf/IStarBaseApprove.sol";
import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
contract StarBaseApprove is InitializableOwnable {
using SafeERC20 for IERC20;
uint256 private constant _TIMELOCK_DURATION_ = 3 days;
uint256 private constant _TIMELOCK_EMERGENCY_DURATION_ = 24 hours;
uint256 public _TIMELOCK_;
address public _PENDING_StarBase_PROXY_;
address public _StarBase_PROXY_;
event ClaimTokens(address indexed token, address indexed who, address indexed dest, uint160 amount);
event LockSetProxy();
event AddStarBaseProxy(address indexed newStarBaseProxy);
event UnlockSetProxy(address newStarBaseProxy);
modifier notLocked() {
require(_TIMELOCK_ <= block.timestamp, "SA: PROXY SET IS TIMELOCKED");
_;
}
constructor(address owner, address _StarBase_PROXY) {
Common._validateAddress(owner);
initOwner(owner);
require(
_checkIfContractSupportsInterface(_StarBase_PROXY, type(IStarBaseApproveProxy).interfaceId),
"SA: ADDRESS_DOES_NOT_IMPLEMENT_REQUIRED_METHODS"
);
_StarBase_PROXY_ = _StarBase_PROXY;
}
function unlockSetProxy(address newStarBaseProxy) external onlyOwner {
Common._validateAddress(newStarBaseProxy);
require(
_checkIfContractSupportsInterface(newStarBaseProxy, type(IStarBaseApproveProxy).interfaceId),
"SA: ADDRESS_DOES_NOT_IMPLEMENT_REQUIRED_METHODS"
);
_TIMELOCK_ = (_StarBase_PROXY_ == address(0))
? block.timestamp + _TIMELOCK_EMERGENCY_DURATION_
: block.timestamp + _TIMELOCK_DURATION_;
_PENDING_StarBase_PROXY_ = newStarBaseProxy;
emit UnlockSetProxy(newStarBaseProxy);
}
function lockSetProxy() public onlyOwner {
_PENDING_StarBase_PROXY_ = address(0);
_TIMELOCK_ = 0;
emit LockSetProxy();
}
function addStarBaseProxy() external onlyOwner notLocked {
_StarBase_PROXY_ = _PENDING_StarBase_PROXY_;
lockSetProxy();
emit AddStarBaseProxy(_PENDING_StarBase_PROXY_);
}
function claimTokens(address token, address who, address dest, uint160 amount) external {
Common._validateAddress(token);
Common._validateAddress(who);
Common._validateAddress(dest);
require(msg.sender == _StarBase_PROXY_, "SA: ACCESS RESTRICTED TO APPROVED PROXY");
if (amount > 0) {
IERC20(token).safeTransferFrom(who, dest, amount);
}
emit ClaimTokens(token, who, dest, amount);
}
function _checkIfContractSupportsInterface(address _contract, bytes4 interfaceId) internal view returns (bool) {
(bool success, bytes memory result) = _contract.staticcall(
abi.encodeWithSelector(ERC165.supportsInterface.selector, interfaceId)
);
if (success && result.length == 32) {
return abi.decode(result, (bool));
}
return false;
}
function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return interfaceId == type(IStarBaseApprove).interfaceId;
}
}
{
"compilationTarget": {
"src/StarBaseApprove.sol": "StarBaseApprove"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"_StarBase_PROXY","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newStarBaseProxy","type":"address"}],"name":"AddStarBaseProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":true,"internalType":"address","name":"dest","type":"address"},{"indexed":false,"internalType":"uint160","name":"amount","type":"uint160"}],"name":"ClaimTokens","type":"event"},{"anonymous":false,"inputs":[],"name":"LockSetProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferPrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newStarBaseProxy","type":"address"}],"name":"UnlockSetProxy","type":"event"},{"inputs":[],"name":"_NEW_OWNER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_OWNER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_PENDING_StarBase_PROXY_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_StarBase_PROXY_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_TIMELOCK_","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addStarBaseProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"who","type":"address"},{"internalType":"address","name":"dest","type":"address"},{"internalType":"uint160","name":"amount","type":"uint160"}],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"initOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockSetProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newStarBaseProxy","type":"address"}],"name":"unlockSetProxy","outputs":[],"stateMutability":"nonpayable","type":"function"}]