编译器
0.8.10+commit.fc410830
文件 1 的 4:EulDistributor.sol
pragma solidity ^0.8.0;
import "../vendor/MerkleProof.sol";
import "../Utils.sol";
interface IEulStakes {
function stakeGift(address beneficiary, address underlying, uint amount) external;
}
contract EulDistributor {
address public immutable eul;
address public immutable eulStakes;
string public constant name = "EUL Distributor";
address public owner;
bytes32 public currRoot;
bytes32 public prevRoot;
mapping(address => mapping(address => uint)) public claimed;
event OwnerChanged(address indexed newOwner);
constructor(address eul_, address eulStakes_) {
eul = eul_;
eulStakes = eulStakes_;
owner = msg.sender;
Utils.safeApprove(eul_, eulStakes_, type(uint).max);
}
modifier onlyOwner {
require(msg.sender == owner, "unauthorized");
_;
}
function transferOwnership(address newOwner) external onlyOwner {
owner = newOwner;
emit OwnerChanged(newOwner);
}
function updateRoot(bytes32 newRoot) external onlyOwner {
prevRoot = currRoot;
currRoot = newRoot;
}
function claim(address account, address token, uint claimable, bytes32[] calldata proof, address stake) external {
bytes32 candidateRoot = MerkleProof.processProof(proof, keccak256(abi.encodePacked(account, token, claimable)));
require(candidateRoot == currRoot || candidateRoot == prevRoot, "proof invalid/expired");
uint alreadyClaimed = claimed[account][token];
require(claimable > alreadyClaimed, "already claimed");
uint amount;
unchecked {
amount = claimable - alreadyClaimed;
}
claimed[account][token] = claimable;
if (stake == address(0)) {
Utils.safeTransfer(token, account, amount);
} else {
require(msg.sender == account, "can only auto-stake for yourself");
require(token == eul, "can only auto-stake EUL");
IEulStakes(eulStakes).stakeGift(account, stake, amount);
}
}
}
文件 2 的 4:Interfaces.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
interface IERC20Permit {
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external;
function permit(address owner, address spender, uint value, uint deadline, bytes calldata signature) external;
}
interface IERC3156FlashBorrower {
function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32);
}
interface IERC3156FlashLender {
function maxFlashLoan(address token) external view returns (uint256);
function flashFee(address token, uint256 amount) external view returns (uint256);
function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data) external returns (bool);
}
文件 3 的 4:MerkleProof.sol
pragma solidity ^0.8.0;
library MerkleProof {
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
computedHash = _efficientHash(computedHash, proofElement);
} else {
computedHash = _efficientHash(proofElement, computedHash);
}
}
return computedHash;
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 4 的 4:Utils.sol
pragma solidity ^0.8.0;
import "./Interfaces.sol";
library Utils {
function safeTransferFrom(address token, address from, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), string(data));
}
function safeTransfer(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), string(data));
}
function safeApprove(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), string(data));
}
}
{
"compilationTarget": {
"contracts/mining/EulDistributor.sol": "EulDistributor"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"eul_","type":"address"},{"internalType":"address","name":"eulStakes_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"claimable","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"stake","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eul","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eulStakes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newRoot","type":"bytes32"}],"name":"updateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"}]