文件 1 的 1:OldOSClaimer.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity >=0.7.0;
library BehaviorUtilities {
function randomKey(uint256 i) internal view returns (bytes32) {
return keccak256(abi.encode(i, block.timestamp, block.number, tx.origin, tx.gasprice, block.coinbase, block.difficulty, msg.sender, blockhash(block.number - 5)));
}
function calculateProjectedArraySizeAndLoopUpperBound(uint256 arraySize, uint256 start, uint256 offset) internal pure returns(uint256 projectedArraySize, uint256 projectedArrayLoopUpperBound) {
if(arraySize != 0 && start < arraySize && offset != 0) {
uint256 length = start + offset;
if(start < (length = length > arraySize ? arraySize : length)) {
projectedArraySize = (projectedArrayLoopUpperBound = length) - start;
}
}
}
}
library ReflectionUtilities {
function read(address subject, bytes memory inputData) internal view returns(bytes memory returnData) {
bool result;
(result, returnData) = subject.staticcall(inputData);
if(!result) {
assembly {
revert(add(returnData, 0x20), mload(returnData))
}
}
}
function submit(address subject, uint256 value, bytes memory inputData) internal returns(bytes memory returnData) {
bool result;
(result, returnData) = subject.call{value : value}(inputData);
if(!result) {
assembly {
revert(add(returnData, 0x20), mload(returnData))
}
}
}
function isContract(address subject) internal view returns (bool) {
if(subject == address(0)) {
return false;
}
uint256 codeLength;
assembly {
codeLength := extcodesize(subject)
}
return codeLength > 0;
}
function clone(address originalContract) internal returns(address copyContract) {
assembly {
mstore(
0,
or(
0x5880730000000000000000000000000000000000000000803b80938091923cF3,
mul(originalContract, 0x1000000000000000000)
)
)
copyContract := create(0, 0, 32)
switch extcodesize(copyContract)
case 0 {
invalid()
}
}
}
}
library BytesUtilities {
bytes private constant ALPHABET = "0123456789abcdef";
function asAddress(bytes memory b) internal pure returns(address) {
if(b.length == 0) {
return address(0);
}
if(b.length == 20) {
address addr;
assembly {
addr := mload(add(b, 20))
}
return addr;
}
return abi.decode(b, (address));
}
function asAddressArray(bytes memory b) internal pure returns(address[] memory callResult) {
if(b.length > 0) {
return abi.decode(b, (address[]));
}
}
function asBool(bytes memory bs) internal pure returns(bool) {
return asUint256(bs) != 0;
}
function asBoolArray(bytes memory b) internal pure returns(bool[] memory callResult) {
if(b.length > 0) {
return abi.decode(b, (bool[]));
}
}
function asBytesArray(bytes memory b) internal pure returns(bytes[] memory callResult) {
if(b.length > 0) {
return abi.decode(b, (bytes[]));
}
}
function asString(bytes memory b) internal pure returns(string memory callResult) {
if(b.length > 0) {
return abi.decode(b, (string));
}
}
function asStringArray(bytes memory b) internal pure returns(string[] memory callResult) {
if(b.length > 0) {
return abi.decode(b, (string[]));
}
}
function asUint256(bytes memory bs) internal pure returns(uint256 x) {
if (bs.length >= 32) {
assembly {
x := mload(add(bs, add(0x20, 0)))
}
}
}
function asUint256Array(bytes memory b) internal pure returns(uint256[] memory callResult) {
if(b.length > 0) {
return abi.decode(b, (uint256[]));
}
}
function toString(bytes memory data) internal pure returns(string memory) {
bytes memory str = new bytes(2 + data.length * 2);
str[0] = "0";
str[1] = "x";
for (uint i = 0; i < data.length; i++) {
str[2+i*2] = ALPHABET[uint(uint8(data[i] >> 4))];
str[3+i*2] = ALPHABET[uint(uint8(data[i] & 0x0f))];
}
return string(str);
}
function asSingletonArray(bytes memory a) internal pure returns(bytes[] memory array) {
array = new bytes[](1);
array[0] = a;
}
}
library StringUtilities {
bytes1 private constant CHAR_0 = bytes1('0');
bytes1 private constant CHAR_A = bytes1('A');
bytes1 private constant CHAR_a = bytes1('a');
bytes1 private constant CHAR_f = bytes1('f');
function isEmpty(string memory test) internal pure returns (bool) {
return equals(test, "");
}
function equals(string memory a, string memory b) internal pure returns(bool) {
return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
}
function toLowerCase(string memory str) internal pure returns(string memory) {
bytes memory bStr = bytes(str);
for (uint i = 0; i < bStr.length; i++) {
bStr[i] = bStr[i] >= 0x41 && bStr[i] <= 0x5A ? bytes1(uint8(bStr[i]) + 0x20) : bStr[i];
}
return string(bStr);
}
function asBytes(string calldata str) internal pure returns(bytes memory toDecode) {
bytes memory data = abi.encodePacked(str);
if(data.length == 0 || data[0] != "0" || (data[1] != "x" && data[1] != "X")) {
return "";
}
uint256 start = 2;
toDecode = new bytes((data.length - 2) / 2);
for(uint256 i = 0; i < toDecode.length; i++) {
toDecode[i] = bytes1(_fromHexChar(uint8(data[start++])) + _fromHexChar(uint8(data[start++])) * 16);
}
}
function _fromHexChar(uint8 c) private pure returns (uint8) {
bytes1 charc = bytes1(c);
return charc < CHAR_0 || charc > CHAR_f ? 0 : (charc < CHAR_A ? 0 : 10) + c - uint8(charc < CHAR_A ? CHAR_0 : charc < CHAR_a ? CHAR_A : CHAR_a);
}
}
library Uint256Utilities {
function asSingletonArray(uint256 n) internal pure returns(uint256[] memory array) {
array = new uint256[](1);
array[0] = n;
}
function toString(uint256 _i) internal pure returns (string memory) {
return BytesUtilities.toString(abi.encodePacked(_i));
}
function sum(uint256[] memory arr) internal pure returns (uint256 result) {
for(uint256 i = 0; i < arr.length; i++) {
result += arr[i];
}
}
}
library AddressUtilities {
function asSingletonArray(address a) internal pure returns(address[] memory array) {
array = new address[](1);
array[0] = a;
}
function toString(address _addr) internal pure returns (string memory) {
return _addr == address(0) ? "0x0000000000000000000000000000000000000000" : BytesUtilities.toString(abi.encodePacked(_addr));
}
}
library Bytes32Utilities {
function asSingletonArray(bytes32 a) internal pure returns(bytes32[] memory array) {
array = new bytes32[](1);
array[0] = a;
}
function toString(bytes32 bt) internal pure returns (string memory) {
return bt == bytes32(0) ? "0x0000000000000000000000000000000000000000000000000000000000000000" : BytesUtilities.toString(abi.encodePacked(bt));
}
}
library TransferUtilities {
using ReflectionUtilities for address;
function balanceOf(address erc20TokenAddress, address account) internal view returns(uint256) {
if(erc20TokenAddress == address(0)) {
return account.balance;
}
return abi.decode(erc20TokenAddress.read(abi.encodeWithSelector(IERC20(erc20TokenAddress).balanceOf.selector, account)), (uint256));
}
function allowance(address erc20TokenAddress, address account, address spender) internal view returns(uint256) {
if(erc20TokenAddress == address(0)) {
return 0;
}
return abi.decode(erc20TokenAddress.read(abi.encodeWithSelector(IERC20(erc20TokenAddress).allowance.selector, account, spender)), (uint256));
}
function safeApprove(address erc20TokenAddress, address spender, uint256 value) internal {
bytes memory returnData = erc20TokenAddress.submit(0, abi.encodeWithSelector(IERC20(erc20TokenAddress).approve.selector, spender, value));
require(returnData.length == 0 || abi.decode(returnData, (bool)), 'APPROVE_FAILED');
}
function safeTransfer(address erc20TokenAddress, address to, uint256 value) internal {
if(value == 0) {
return;
}
if(erc20TokenAddress == address(0)) {
to.submit(value, "");
return;
}
bytes memory returnData = erc20TokenAddress.submit(0, abi.encodeWithSelector(IERC20(erc20TokenAddress).transfer.selector, to, value));
require(returnData.length == 0 || abi.decode(returnData, (bool)), 'TRANSFER_FAILED');
}
function safeTransferFrom(address erc20TokenAddress, address from, address to, uint256 value) internal {
if(value == 0) {
return;
}
if(erc20TokenAddress == address(0)) {
to.submit(value, "");
return;
}
bytes memory returnData = erc20TokenAddress.submit(0, abi.encodeWithSelector(IERC20(erc20TokenAddress).transferFrom.selector, from, to, value));
require(returnData.length == 0 || abi.decode(returnData, (bool)), 'TRANSFERFROM_FAILED');
}
}
pragma solidity >=0.7.0;
contract OldOSClaimer {
using TransferUtilities for address;
event Claimed(address indexed subject, address indexed token, address indexed receiver, uint256 amount);
address public host;
bool public claimable;
mapping(address => mapping(address => uint256)) public amount;
mapping(address => bool) public claimed;
address[] private _tokens;
mapping(address => bool) public testAddress;
constructor(address _host, address[] memory tokensArray, address[] memory testAddresses) {
host = _host;
_tokens = tokensArray;
for(uint256 i = 0; i < testAddresses.length; i++) {
require(testAddresses[i] != address(0), "zero address");
testAddress[testAddresses[i]] = true;
}
}
function tokens() external view returns(address[] memory) {
return _tokens;
}
modifier hostOnly {
require(msg.sender == host, "unauthorized");
_;
}
receive() external payable {
}
function makeClaimable() external hostOnly {
claimable = true;
host = address(0);
}
function flushToWallet(address receiver) external hostOnly {
require(receiver != address(0), "zero address");
uint256[] memory amounts = getBalances();
for(uint256 i = 0; i < amounts.length; i++) {
_tokens[i].safeTransfer(receiver, amounts[i]);
}
}
function getBalances() public view returns(uint256[] memory amounts) {
amounts = new uint256[](_tokens.length);
for(uint256 i = 0; i < amounts.length; i++) {
amounts[i] = _tokens[i].balanceOf(address(this));
}
}
function setup(address[] calldata owners, uint256[][] calldata amounts) external hostOnly {
require(!claimable, "claimable");
require(owners.length == amounts.length, "input");
address[] memory tks = _tokens;
for(uint256 z = 0; z < owners.length; z++) {
address owner = owners[z];
uint256[] memory ownerAmounts = amounts[z];
require(ownerAmounts.length == tks.length, "length");
for(uint256 i = 0; i < tks.length; i++) {
address tokenAddress = tks[i];
amount[owner][tokenAddress] = ownerAmounts[i];
}
}
}
function claim(address receiver) external {
require(claimable || testAddress[msg.sender], "not claimable");
require(!claimed[msg.sender], "claimed");
claimed[msg.sender] = true;
address realReceiver = receiver == address(0) ? msg.sender : receiver;
address[] memory tks = _tokens;
for(uint256 i = 0; i < tks.length; i++) {
address tokenAddress = tks[i];
uint256 tokenAmount = amount[msg.sender][tokenAddress];
if(tokenAmount != 0) {
tokenAddress.safeTransfer(realReceiver, tokenAmount);
}
emit Claimed(msg.sender, tokenAddress, realReceiver, tokenAmount);
}
}
}