编译器
0.8.19+commit.7dd6d404
文件 1 的 8:AaveV3Adapter.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {BaseAdapter} from "./BaseAdapter.sol";
interface IPool {
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
}
interface AToken {
function UNDERLYING_ASSET_ADDRESS() view external returns (address);
function POOL() view external returns (address);
}
interface IRewardsController {
function claimAllRewards(address[] calldata assets, address to) external
returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
}
contract AaveV3Adapter is BaseAdapter {
using SafeTransferLib for ERC20;
ERC20 public immutable aToken;
IPool public immutable lendingPool;
IRewardsController public immutable rewardsController;
constructor(
address aToken_,
address rewardRecipient_,
address rewardsController_,
address owner_
) BaseAdapter(AToken(aToken_).UNDERLYING_ASSET_ADDRESS(), rewardRecipient_, owner_) {
lendingPool = IPool(AToken(aToken_).POOL());
aToken = ERC20(aToken_);
rewardsController = IRewardsController(rewardsController_);
asset.safeApprove(address(lendingPool), type(uint256).max);
}
function claimRewards() external {
require(msg.sender == rewardRecipient, "not rewardRecipient");
address[] memory assets = new address[](1);
assets[0] = address(aToken);
rewardsController.claimAllRewards(assets, rewardRecipient);
}
function forceDeposit(uint assets) internal override {
lendingPool.supply(address(asset), assets, address(this), 0);
}
function forceRedeem(uint assets, address receiver) internal override {
lendingPool.withdraw(address(asset), assets, receiver);
}
function totalAssets() public view override returns (uint256) {
return aToken.balanceOf(address(this)) + asset.balanceOf(address(this));
}
function refreshApproval() external override {
asset.safeApprove(address(lendingPool), 0);
asset.safeApprove(address(lendingPool), type(uint256).max);
}
}
文件 2 的 8:BaseAdapter.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {Owned} from "solmate/src/auth/Owned.sol";
abstract contract BaseAdapter is Owned {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
ERC20 public immutable asset;
address public rewardRecipient;
uint public immutable DIVISOR;
uint public totalSupply;
constructor(
address asset_,
address rewardRecipient_,
address owner_
) Owned(owner_) {
asset = ERC20(asset_);
rewardRecipient = rewardRecipient_;
DIVISOR = 10**asset.decimals();
}
function setRewardRecipient(address _rewardRecipient) external onlyOwner() {
rewardRecipient = _rewardRecipient;
}
function triggerDeposit(uint amount, uint maxToPull) external onlyOwner() {
forceDepositAndCheck(amount, maxToPull);
}
function forceDepositAndCheck(uint amount, uint maxToPull) internal {
uint oldTotalAssets = totalAssets();
forceDeposit(amount);
uint newTotalAssets = totalAssets();
if(newTotalAssets < oldTotalAssets){
uint pullAmount = oldTotalAssets - newTotalAssets;
require(pullAmount < maxToPull, ">maxToPull");
asset.safeTransferFrom(msg.sender, address(this), pullAmount);
}
}
function forceDeposit(uint assets) internal virtual;
function deposit(uint256 assets) internal returns (uint shares) {
shares = totalSupply == 0 ? assets : assets.mulDivDown(totalSupply, totalAssets());
totalSupply += shares;
}
function forceRedeem(uint assets, address receiver) internal virtual;
function redeem(uint256 shares, address receiver) internal {
uint assets = convertToAssets(shares);
totalSupply -= shares;
if(assets <= asset.balanceOf(address(this))){
asset.safeTransfer(receiver, assets);
} else {
forceRedeem(assets, receiver);
}
}
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function refreshApproval() external virtual;
}
文件 3 的 8:BoringBatchable.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
interface IERC20Permit{
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
contract BaseBoringBatchable {
function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
if (_returnData.length < 68) return "Transaction reverted silently";
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function batch(bytes[] calldata calls, bool revertOnFail) external payable {
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
if (!success && revertOnFail) {
revert(_getRevertMsg(result));
}
}
}
}
contract BoringBatchable is BaseBoringBatchable {
function permitToken(
IERC20Permit token,
address from,
address to,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public {
token.permit(from, to, amount, deadline, v, r, s);
}
}
文件 4 的 8:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 5 的 8:FixedPointMathLib.sol
pragma solidity >=0.8.0;
library FixedPointMathLib {
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18;
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD);
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 {
z := scalar
}
default {
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
z := scalar
}
default {
z := x
}
let half := shr(1, scalar)
for {
n := shr(1, n)
} n {
n := shr(1, n)
} {
if shr(128, x) {
revert(0, 0)
}
let xx := mul(x, x)
let xxRound := add(xx, half)
if lt(xxRound, xx) {
revert(0, 0)
}
x := div(xxRound, scalar)
if mod(n, 2) {
let zx := mul(z, x)
if iszero(eq(div(zx, x), z)) {
if iszero(iszero(x)) {
revert(0, 0)
}
}
let zxRound := add(zx, half)
if lt(zxRound, zx) {
revert(0, 0)
}
z := div(zxRound, scalar)
}
}
}
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
let y := x
z := 181
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
z := shr(18, mul(z, add(y, 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly {
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}
文件 6 的 8:Owned.sol
pragma solidity >=0.8.0;
abstract contract Owned {
event OwnershipTransferred(address indexed user, address indexed newOwner);
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
文件 7 的 8:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 8 的 8:Subs.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {BoringBatchable} from "./fork/BoringBatchable.sol";
import {AaveV3Adapter} from "./yield/AaveV3Adapter.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
contract Subs is BoringBatchable, AaveV3Adapter {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
uint public immutable periodDuration;
address public immutable feeCollector;
uint public currentPeriod;
uint public sharesAccumulator;
mapping(address => mapping(uint256 => uint256)) public receiverAmountToExpire;
struct ReceiverBalance {
uint256 balance;
uint256 amountPerPeriod;
uint256 lastUpdate;
}
mapping(address => ReceiverBalance) public receiverBalances;
mapping(uint256 => uint256) public sharesPerPeriod;
mapping(bytes32 => bool) public subs;
event NewSubscription(address owner, uint initialPeriod, uint expirationDate, uint amountPerCycle, address receiver, uint256 accumulator, uint256 initialShares, bytes32 subId, bytes32 paymentId);
event NewDelayedSubscription(address owner, uint initialPeriod, uint expirationDate, uint amountPerCycle, address receiver, uint256 accumulator, uint256 initialShares, bytes32 subId, uint instantPayment, bytes32 paymentId);
event Unsubscribe(bytes32 subId);
constructor(uint _periodDuration, address _vault, address _feeCollector, uint _currentPeriod, address rewardRecipient_,
address stakingRewards_, address owner_) AaveV3Adapter(_vault, rewardRecipient_, stakingRewards_, owner_){
require(_periodDuration >= 7 days, "periodDuration too smol");
periodDuration = _periodDuration;
currentPeriod = _currentPeriod;
require(currentPeriod < block.timestamp);
feeCollector = _feeCollector;
}
function _updateGlobal(uint limit) private {
if(block.timestamp > currentPeriod + periodDuration){
uint shares = convertToShares(DIVISOR);
do {
sharesPerPeriod[currentPeriod] = shares;
currentPeriod += periodDuration;
sharesAccumulator += shares;
} while(limit > currentPeriod + periodDuration);
}
}
function min(uint a, uint b) pure internal returns (uint) {
return a>b?b:a;
}
function _updateReceiver(address receiver, uint limit) private {
ReceiverBalance storage bal = receiverBalances[receiver];
uint lastUpdate = bal.lastUpdate;
if(lastUpdate + periodDuration < block.timestamp){
_updateGlobal(limit);
if(lastUpdate == 0){
lastUpdate = currentPeriod;
} else {
uint balance = bal.balance;
uint amountPerPeriod = bal.amountPerPeriod;
uint limitToFill = min(currentPeriod, limit);
do {
amountPerPeriod -= receiverAmountToExpire[receiver][lastUpdate];
balance += (amountPerPeriod * sharesPerPeriod[lastUpdate]) / DIVISOR;
lastUpdate += periodDuration;
} while (lastUpdate < limitToFill);
bal.balance = balance;
bal.amountPerPeriod = amountPerPeriod;
}
bal.lastUpdate = lastUpdate;
}
}
function partialUpdateReceiver(address receiver, uint limit) external {
require(limit < block.timestamp, "limit too big");
_updateReceiver(receiver, limit);
}
function getSubId(address owner, uint initialPeriod, uint expirationDate,
uint amountPerCycle, address receiver, uint256 accumulator, uint256 initialShares) public pure returns (bytes32 id){
id = keccak256(
abi.encode(
owner,
initialPeriod,
expirationDate,
amountPerCycle,
receiver,
accumulator,
initialShares
)
);
}
function _subscribe(address receiver, uint amountPerCycle, uint256 amountForFuture, uint claimableThisPeriod) internal
returns (uint expirationDate, uint256, bytes32) {
uint amount = amountForFuture + claimableThisPeriod;
uint cycles = amountForFuture/amountPerCycle;
(uint shares) = deposit(amount);
asset.safeTransferFrom(msg.sender, address(this), amount);
uint expiration = currentPeriod + periodDuration*cycles;
receiverAmountToExpire[receiver][expiration] += amountPerCycle;
receiverBalances[receiver].amountPerPeriod += amountPerCycle;
receiverBalances[receiver].balance += (shares * claimableThisPeriod) / amount;
uint sharesLeft = (amountForFuture * shares) / amount;
bytes32 subId = getSubId(msg.sender, currentPeriod, expiration, amountPerCycle, receiver, sharesAccumulator, sharesLeft);
require(subs[subId] == false, "duplicated sub");
subs[subId] = true;
return (expiration, sharesLeft, subId);
}
function subscribe(address receiver, uint amountPerCycle, uint256 amountForFuture, bytes32 paymentId) external {
_updateReceiver(receiver, block.timestamp);
uint claimableThisPeriod = (amountPerCycle * (currentPeriod + periodDuration - block.timestamp)) / periodDuration;
(uint expirationDate, uint256 sharesLeft, bytes32 subId) = _subscribe(receiver, amountPerCycle, amountForFuture, claimableThisPeriod);
emit NewSubscription(msg.sender, currentPeriod, expirationDate, amountPerCycle, receiver, sharesAccumulator, sharesLeft, subId, paymentId);
}
function subscribeForNextPeriod(address receiver, uint amountPerCycle, uint256 amountForFuture, uint256 instantPayment, bytes32 paymentId) external {
require(amountForFuture >= amountPerCycle, "amountForFuture < amountPerCycle");
_updateReceiver(receiver, block.timestamp);
(uint expirationDate, uint256 sharesLeft, bytes32 subId) = _subscribe(receiver, amountPerCycle, amountForFuture, instantPayment);
emit NewDelayedSubscription(msg.sender, currentPeriod, expirationDate, amountPerCycle, receiver, sharesAccumulator, sharesLeft, subId, instantPayment, paymentId);
}
function unsubscribe(uint initialPeriod, uint expirationDate, uint amountPerCycle, address receiver, uint256 accumulator, uint256 initialShares) external {
_updateGlobal(block.timestamp);
bytes32 subId = getSubId(msg.sender, initialPeriod, expirationDate, amountPerCycle, receiver, accumulator, initialShares);
require(subs[subId] == true, "sub doesn't exist");
delete subs[subId];
if(expirationDate >= block.timestamp){
uint sharesPaid = (sharesAccumulator - accumulator).mulDivUp(amountPerCycle, DIVISOR);
uint sharesLeft = initialShares - sharesPaid;
redeem(sharesLeft, msg.sender);
receiverAmountToExpire[receiver][expirationDate] -= amountPerCycle;
receiverAmountToExpire[receiver][currentPeriod] += amountPerCycle;
} else {
uint subsetAccumulator = 0;
while(initialPeriod < expirationDate){
subsetAccumulator += sharesPerPeriod[initialPeriod];
initialPeriod += periodDuration;
}
redeem(initialShares - subsetAccumulator.mulDivUp(amountPerCycle, DIVISOR), msg.sender);
}
emit Unsubscribe(subId);
}
function claim(uint256 amount) external {
_updateReceiver(msg.sender, block.timestamp);
receiverBalances[msg.sender].balance -= amount;
redeem((amount * 99) / 100, msg.sender);
receiverBalances[feeCollector].balance += amount / 100;
}
}
{
"compilationTarget": {
"contracts/Subs.sol": "Subs"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 4294967
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"uint256","name":"_periodDuration","type":"uint256"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"uint256","name":"_currentPeriod","type":"uint256"},{"internalType":"address","name":"rewardRecipient_","type":"address"},{"internalType":"address","name":"stakingRewards_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expirationDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"accumulator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialShares","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"subId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"instantPayment","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"paymentId","type":"bytes32"}],"name":"NewDelayedSubscription","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expirationDate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"accumulator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialShares","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"subId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"paymentId","type":"bytes32"}],"name":"NewSubscription","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"subId","type":"bytes32"}],"name":"Unsubscribe","type":"event"},{"inputs":[],"name":"DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aToken","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"},{"internalType":"bool","name":"revertOnFail","type":"bool"}],"name":"batch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"initialPeriod","type":"uint256"},{"internalType":"uint256","name":"expirationDate","type":"uint256"},{"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"accumulator","type":"uint256"},{"internalType":"uint256","name":"initialShares","type":"uint256"}],"name":"getSubId","outputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"lendingPool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"partialUpdateReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"periodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Permit","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"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"}],"name":"permitToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"receiverAmountToExpire","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"receiverBalances","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"amountPerPeriod","type":"uint256"},{"internalType":"uint256","name":"lastUpdate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refreshApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsController","outputs":[{"internalType":"contract IRewardsController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardRecipient","type":"address"}],"name":"setRewardRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharesAccumulator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"sharesPerPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"subs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"internalType":"uint256","name":"amountForFuture","type":"uint256"},{"internalType":"bytes32","name":"paymentId","type":"bytes32"}],"name":"subscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"internalType":"uint256","name":"amountForFuture","type":"uint256"},{"internalType":"uint256","name":"instantPayment","type":"uint256"},{"internalType":"bytes32","name":"paymentId","type":"bytes32"}],"name":"subscribeForNextPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maxToPull","type":"uint256"}],"name":"triggerDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialPeriod","type":"uint256"},{"internalType":"uint256","name":"expirationDate","type":"uint256"},{"internalType":"uint256","name":"amountPerCycle","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"accumulator","type":"uint256"},{"internalType":"uint256","name":"initialShares","type":"uint256"}],"name":"unsubscribe","outputs":[],"stateMutability":"nonpayable","type":"function"}]