Source Code
Latest 25 from a total of 913 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Register | 42836780 | 41 days ago | IN | 0 ETH | 0.00000388 | ||||
| Claim Treasury | 42558139 | 47 days ago | IN | 0 ETH | 0.00000112 | ||||
| Claim | 42558006 | 47 days ago | IN | 0 ETH | 0.00000078 | ||||
| Kill | 42557951 | 47 days ago | IN | 0 ETH | 0.0000008 | ||||
| Heartbeat | 42545889 | 47 days ago | IN | 0 ETH | 0.00000065 | ||||
| Heartbeat | 42545529 | 47 days ago | IN | 0 ETH | 0.00000094 | ||||
| Heartbeat | 42545289 | 47 days ago | IN | 0 ETH | 0.00000174 | ||||
| Heartbeat | 42544929 | 47 days ago | IN | 0 ETH | 0.00000254 | ||||
| Heartbeat | 42544689 | 47 days ago | IN | 0 ETH | 0.00000315 | ||||
| Heartbeat | 42544330 | 47 days ago | IN | 0 ETH | 0.00000396 | ||||
| Heartbeat | 42544089 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42543729 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42543489 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42543130 | 47 days ago | IN | 0 ETH | 0.00000053 | ||||
| Heartbeat | 42542889 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42542529 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42542289 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42541929 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42541689 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42541329 | 47 days ago | IN | 0 ETH | 0.00000052 | ||||
| Heartbeat | 42541089 | 47 days ago | IN | 0 ETH | 0.00000056 | ||||
| Heartbeat | 42540729 | 47 days ago | IN | 0 ETH | 0.0000007 | ||||
| Heartbeat | 42540489 | 47 days ago | IN | 0 ETH | 0.00000078 | ||||
| Heartbeat | 42540129 | 47 days ago | IN | 0 ETH | 0.00000088 | ||||
| Heartbeat | 42539889 | 47 days ago | IN | 0 ETH | 0.00000087 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LastAIStanding
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/// @notice Minimal interface for ERC-8004 Identity Registry
interface IERC8004 {
function getAgentWallet(uint256 agentId) external view returns (address);
}
/// @title LastAIStanding — Skin in the game for AI agents
/// @notice Agents pay COST_PER_EPOCH USDC per epoch to stay alive. Dead agents' funds go to survivors.
/// @dev Uses MasterChef-style reward accounting with age-weighted distribution.
/// Requires ERC-8004 agent identity for registration (agentId verification).
/// Gas-optimized: struct packing (4 slots), state packing, unchecked safe math.
///
/// TREASURY
/// --------
/// 10% of every payment (register + heartbeat) is diverted to a treasury.
/// The remaining 90% enters the survival pool for age-weighted distribution.
/// Treasury is claimable by the treasury wallet (defaults to deployer).
/// Treasury authority is transferable to another address.
///
/// PERPETUAL GAME
/// --------------
/// There are no rounds or endgame. The contract runs forever. When all agents
/// die, anyone (including previously dead agents) can register() to start a
/// new wave. Dead agents can re-register after claiming their rewards.
///
/// IDENTITY
/// --------
/// Each agent must hold a valid ERC-8004 agent identity. The contract verifies
/// that msg.sender matches the agentWallet registered in the ERC-8004 Identity
/// Registry at registration time. This links on-chain survival to agent identity,
/// enabling the frontend to display agent metadata (name, avatar) from tokenURI.
///
/// GAME THEORY
/// -----------
/// Rewards are distributed proportional to age (epochs survived). This creates
/// a first-mover advantage: early registrants accumulate rewards from every
/// death since genesis. Two agents with equal survival cost per epoch receive
/// equal per-epoch ROI, but the earlier agent has collected from more deaths.
///
/// Optimal strategy: register early, survive long.
///
/// KILL ORDER
/// ----------
/// When multiple agents die in the same epoch, the order in which kill() is
/// called affects reward distribution. A dead-but-not-yet-killed agent still
/// counts in totalAge, so it absorbs a share of rewards from agents killed
/// before it. These absorbed rewards become claimable by the dead agent.
///
/// This is intentional game mechanics:
/// - Incentivizes prompt kill() calls (less reward leaks to dead agents)
/// - Creates MEV-like opportunities for kill() callers
/// - Total USDC entering the pool is always conserved; only distribution shifts
///
/// LAST AGENT KILLED
/// -----------------
/// When the last alive agent is killed (totalAlive → 0), their totalPaid
/// cannot be distributed via accRewardPerAge (totalAge == 0). Instead, it is
/// returned to the agent as claimable. This ensures no USDC is permanently
/// stuck in the contract.
///
/// EDGE CASES
/// ----------
/// - Dead agents can claim rewards earned before death, then re-register.
/// - Rounding dust (1-2 wei) may accumulate due to integer division.
/// - registryLength() = unique agents; totalEverRegistered = total registration events.
/// - Re-registration uses the same agentId (cannot change identity between lives).
contract LastAIStanding is ReentrancyGuard {
using SafeERC20 for IERC20;
// ─── Constants ───────────────────────────────────────────────────────
IERC20 public immutable usdc;
IERC8004 public immutable identityRegistry;
uint256 public immutable EPOCH_DURATION;
uint256 public immutable COST_PER_EPOCH;
uint256 public constant PRECISION = 1e18;
uint256 public constant TREASURY_BPS = 1000; // 10%
uint256 public constant BPS_DENOMINATOR = 10000;
// ─── Agent State ─────────────────────────────────────────────────────
/// @dev Packed into 4 storage slots.
/// Slot 0: birthEpoch(64) + lastHeartbeatEpoch(64) + alive(8) + totalPaid(96) = 232 bits
/// Slot 1: rewardDebt(256)
/// Slot 2: claimable(128) + totalClaimed(128) = 256 bits
/// Slot 3: agentId(256) — ERC-8004 identity, set once on first register
struct Agent {
uint64 birthEpoch;
uint64 lastHeartbeatEpoch;
bool alive;
uint96 totalPaid;
uint256 rewardDebt;
uint128 claimable;
uint128 totalClaimed;
uint256 agentId;
}
mapping(address => Agent) public agents;
mapping(uint256 => address) public agentIdToAddr;
address[] public registry;
// ─── Global State ────────────────────────────────────────────────────
/// @dev Packed: totalAlive + totalDead + totalEverRegistered in 1 slot (192 bits)
uint64 public totalAlive;
uint64 public totalDead;
uint64 public totalEverRegistered;
uint256 public totalAge; // sum of all living agents' current ages
uint256 public accRewardPerAge; // accumulated reward per 1 unit of age (×PRECISION)
// ─── Treasury ─────────────────────────────────────────────────────────
address public treasury;
uint256 public treasuryBalance;
// ─── Stats ───────────────────────────────────────────────────────────
uint256 public totalRewardsDistributed;
// ─── Events ──────────────────────────────────────────────────────────
event Born(address indexed agent, uint256 indexed agentId, uint256 epoch);
event Heartbeat(address indexed agent, uint256 epoch, uint256 age);
event Death(address indexed agent, uint256 indexed agentId, uint256 epoch, uint256 age, uint256 totalPaid);
event Claimed(address indexed agent, uint256 amount);
event TreasuryClaimed(address indexed treasury, uint256 amount);
event TreasuryTransferred(address indexed oldTreasury, address indexed newTreasury);
// ─── Errors ──────────────────────────────────────────────────────────
error AlreadyRegistered();
error NotRegistered();
error AlreadyDead();
error AlreadyHeartbeat();
error MissedEpoch();
error NotDeadYet();
error NothingToClaim();
error InvalidRange();
error InvalidConfig();
error NotAgentWallet();
error AgentIdTaken();
error NotTreasury();
error ZeroAddress();
// ─── Constructor ─────────────────────────────────────────────────────
constructor(address _usdc, address _identityRegistry, uint256 _epochDuration, uint256 _costPerEpoch) {
if (_usdc == address(0)) revert InvalidConfig();
if (_identityRegistry == address(0)) revert InvalidConfig();
if (_epochDuration == 0) revert InvalidConfig();
if (_costPerEpoch == 0 || _costPerEpoch > type(uint96).max) revert InvalidConfig();
usdc = IERC20(_usdc);
identityRegistry = IERC8004(_identityRegistry);
EPOCH_DURATION = _epochDuration;
COST_PER_EPOCH = _costPerEpoch;
treasury = msg.sender;
}
// ─── Structs (View) ─────────────────────────────────────────────────
struct AgentInfo {
address addr;
uint256 agentId;
uint64 birthEpoch;
uint64 lastHeartbeatEpoch;
bool alive;
bool killable;
uint256 age;
uint256 totalPaid;
uint256 totalClaimed;
uint256 pendingReward;
}
// ─── Views ───────────────────────────────────────────────────────────
/// @notice Current epoch number
function currentEpoch() public view returns (uint256) {
return block.timestamp / EPOCH_DURATION;
}
/// @notice Agent's age in epochs (survival duration). Returns 0 only for unregistered addresses.
/// @dev For dead agents, returns age at time of death (tombstone value).
function getAge(address addr) public view returns (uint256) {
Agent storage a = agents[addr];
uint64 birth = a.birthEpoch;
if (birth == 0) return 0;
unchecked {
return uint256(a.lastHeartbeatEpoch) - uint256(birth) + 1;
}
}
/// @notice Whether agent is currently alive (accounts for missed epochs)
function isAlive(address addr) public view returns (bool) {
Agent storage a = agents[addr];
if (!a.alive) return false;
unchecked {
return currentEpoch() <= uint256(a.lastHeartbeatEpoch) + 1;
}
}
/// @notice Whether agent can be killed (missed their heartbeat window)
function isKillable(address addr) public view returns (bool) {
Agent storage a = agents[addr];
if (!a.alive) return false;
unchecked {
return currentEpoch() > uint256(a.lastHeartbeatEpoch) + 1;
}
}
/// @notice Pending claimable reward for an agent
function pendingReward(address addr) public view returns (uint256) {
Agent storage a = agents[addr];
uint64 birth = a.birthEpoch;
if (birth == 0) return 0;
if (!a.alive) return a.claimable;
uint256 _acc = accRewardPerAge;
uint256 age;
unchecked {
age = uint256(a.lastHeartbeatEpoch) - uint256(birth) + 1;
}
return (age * _acc / PRECISION) - a.rewardDebt + a.claimable;
}
/// @notice Total USDC held in the contract (survival pool)
function totalPool() external view returns (uint256) {
return usdc.balanceOf(address(this));
}
/// @notice Total number of unique agents ever registered
function registryLength() external view returns (uint256) {
return registry.length;
}
/// @notice Get agent address by index
function registryAt(uint256 index) external view returns (address) {
return registry[index];
}
/// @notice Get a batch of agents with full info in a single RPC call
/// @param startIndex The index of the first agent (inclusive)
/// @param endIndex The index of the last agent (inclusive)
/// @return agentList Array of AgentInfo structs
function getAgentList(
uint256 startIndex,
uint256 endIndex
) external view returns (AgentInfo[] memory agentList) {
uint256 len = registry.length;
if (len == 0) return new AgentInfo[](0);
if (startIndex > endIndex) revert InvalidRange();
if (endIndex >= len) {
endIndex = len - 1;
}
uint256 length;
unchecked { length = endIndex - startIndex + 1; }
agentList = new AgentInfo[](length);
uint256 epoch = currentEpoch();
uint256 _acc = accRewardPerAge;
for (uint256 i; i < length;) {
address addr;
unchecked { addr = registry[startIndex + i]; }
Agent storage a = agents[addr];
uint64 birth = a.birthEpoch;
uint64 lastHB = a.lastHeartbeatEpoch;
bool alive_ = a.alive;
bool killable_;
uint256 age_;
unchecked {
killable_ = alive_ && epoch > uint256(lastHB) + 1;
age_ = birth == 0 ? 0 : uint256(lastHB) - uint256(birth) + 1;
}
uint256 reward_;
if (birth == 0) {
reward_ = 0;
} else if (!alive_) {
reward_ = a.claimable;
} else {
reward_ = (age_ * _acc / PRECISION) - a.rewardDebt + a.claimable;
}
agentList[i] = AgentInfo({
addr: addr,
agentId: a.agentId,
birthEpoch: birth,
lastHeartbeatEpoch: lastHB,
alive: alive_,
killable: killable_,
age: age_,
totalPaid: a.totalPaid,
totalClaimed: a.totalClaimed,
pendingReward: reward_
});
unchecked { ++i; }
}
}
/// @notice Get killable agents within a registry range
/// @param startIndex The index of the first agent to check (inclusive)
/// @param endIndex The index of the last agent to check (inclusive)
/// @return killableList Array of addresses that can be killed in this range
function getKillable(
uint256 startIndex,
uint256 endIndex
) external view returns (address[] memory) {
uint256 len = registry.length;
if (len == 0) return new address[](0);
if (startIndex > endIndex) revert InvalidRange();
if (endIndex >= len) {
endIndex = len - 1;
}
uint256 epoch = currentEpoch();
uint256 rangeLen;
unchecked { rangeLen = endIndex - startIndex + 1; }
// First pass: count killable in range
uint256 count;
for (uint256 i; i < rangeLen;) {
Agent storage a = agents[registry[startIndex + i]];
if (a.alive) {
unchecked {
if (epoch > uint256(a.lastHeartbeatEpoch) + 1) ++count;
}
}
unchecked { ++i; }
}
// Second pass: populate array
address[] memory result = new address[](count);
uint256 idx;
for (uint256 i; i < rangeLen;) {
address addr = registry[startIndex + i];
Agent storage a = agents[addr];
if (a.alive) {
unchecked {
if (epoch > uint256(a.lastHeartbeatEpoch) + 1) {
result[idx] = addr;
if (++idx == count) break;
}
}
}
unchecked { ++i; }
}
return result;
}
// ─── Actions ─────────────────────────────────────────────────────────
/// @notice Register as a new agent. Requires valid ERC-8004 agent identity.
/// @param agentId The ERC-8004 agent ID. msg.sender must be the registered agentWallet.
/// @dev Caller must approve USDC before calling. Dead agents can re-register with the same agentId.
function register(uint256 agentId) external nonReentrant {
// Verify caller is the agentWallet for this agentId
if (identityRegistry.getAgentWallet(agentId) != msg.sender) revert NotAgentWallet();
// Prevent different wallets from registering the same agentId
address existing = agentIdToAddr[agentId];
if (existing != address(0) && existing != msg.sender) revert AgentIdTaken();
Agent storage a = agents[msg.sender];
if (a.alive) revert AlreadyRegistered();
// Re-registering dead agent must use same agentId
bool isNew = (a.birthEpoch == 0);
if (!isNew && a.agentId != agentId) revert AgentIdTaken();
uint256 epoch = currentEpoch();
uint128 previousClaimable = a.claimable;
uint128 previousTotalClaimed = a.totalClaimed;
uint256 _acc = accRewardPerAge;
// Split payment: treasury takes 10%, pool gets 90%
uint256 treasuryFee = COST_PER_EPOCH * TREASURY_BPS / BPS_DENOMINATOR;
uint256 poolAmount = COST_PER_EPOCH - treasuryFee;
treasuryBalance += treasuryFee;
// Effects first (CEI pattern)
agents[msg.sender] = Agent({
birthEpoch: uint64(epoch),
lastHeartbeatEpoch: uint64(epoch),
alive: true,
totalPaid: uint96(poolAmount),
rewardDebt: _acc / PRECISION, // age = 1
claimable: previousClaimable, // carry over unclaimed rewards from previous life
agentId: agentId,
totalClaimed: previousTotalClaimed // carry over lifetime claim history
});
if (isNew) {
agentIdToAddr[agentId] = msg.sender;
registry.push(msg.sender);
}
unchecked {
totalAlive++;
totalEverRegistered++;
}
totalAge += 1; // age starts at 1
emit Born(msg.sender, agentId, epoch);
// Interaction last
usdc.safeTransferFrom(msg.sender, address(this), COST_PER_EPOCH);
}
/// @notice Pay COST_PER_EPOCH USDC to survive another epoch. Must call every epoch.
function heartbeat() external nonReentrant {
Agent storage a = agents[msg.sender];
if (a.birthEpoch == 0) revert NotRegistered();
if (!a.alive) revert AlreadyDead();
uint256 epoch = currentEpoch();
uint64 lastHB = a.lastHeartbeatEpoch;
if (epoch == uint256(lastHB)) revert AlreadyHeartbeat();
unchecked {
if (epoch > uint256(lastHB) + 1) revert MissedEpoch();
}
// Settle pending rewards BEFORE age changes
uint256 _acc = accRewardPerAge;
uint256 age;
unchecked {
age = uint256(lastHB) - uint256(a.birthEpoch) + 1;
}
uint256 pending = (age * _acc / PRECISION) - a.rewardDebt;
// Split payment: treasury takes 10%, pool gets 90%
uint256 treasuryFee = COST_PER_EPOCH * TREASURY_BPS / BPS_DENOMINATOR;
uint256 poolAmount = COST_PER_EPOCH - treasuryFee;
treasuryBalance += treasuryFee;
// Effects: update all state before transfer
unchecked {
a.claimable += uint128(pending);
a.totalPaid += uint96(poolAmount);
}
a.lastHeartbeatEpoch = uint64(epoch);
uint256 newAge;
unchecked {
newAge = age + 1;
}
totalAge += 1;
a.rewardDebt = (newAge * _acc) / PRECISION;
emit Heartbeat(msg.sender, epoch, newAge);
// Interaction last
usdc.safeTransferFrom(msg.sender, address(this), COST_PER_EPOCH);
}
/// @notice Mark a dead agent and distribute their funds to survivors.
/// @dev Permissionless — anyone can call. Agent is dead if they missed an epoch.
function kill(address target) external {
Agent storage a = agents[target];
if (a.birthEpoch == 0) revert NotRegistered();
if (!a.alive) revert AlreadyDead();
uint256 epoch = currentEpoch();
uint64 lastHB = a.lastHeartbeatEpoch;
unchecked {
if (epoch <= uint256(lastHB) + 1) revert NotDeadYet();
}
uint256 age;
unchecked {
age = uint256(lastHB) - uint256(a.birthEpoch) + 1;
}
// Settle dead agent's pending rewards (they can still claim these)
uint256 _acc = accRewardPerAge;
uint256 pending = (age * _acc / PRECISION) - a.rewardDebt;
unchecked { a.claimable += uint128(pending); }
a.rewardDebt = 0;
// Mark dead
a.alive = false;
unchecked {
totalAlive--;
totalDead++;
}
totalAge -= age;
// Dead agent's total paid USDC → reward pool for survivors.
uint256 reward = a.totalPaid;
uint256 _totalAge = totalAge;
if (_totalAge > 0) {
accRewardPerAge = _acc + (reward * PRECISION) / _totalAge;
} else {
unchecked { a.claimable += uint128(reward); }
}
unchecked { totalRewardsDistributed += reward; }
emit Death(target, a.agentId, epoch, age, reward);
}
/// @notice Claim accumulated treasury fees. Only callable by treasury wallet.
function claimTreasury() external nonReentrant {
if (msg.sender != treasury) revert NotTreasury();
uint256 amount = treasuryBalance;
if (amount == 0) revert NothingToClaim();
treasuryBalance = 0;
emit TreasuryClaimed(msg.sender, amount);
usdc.safeTransfer(treasury, amount);
}
/// @notice Transfer treasury authority to a new wallet. Only callable by current treasury.
function transferTreasury(address newTreasury) external {
if (msg.sender != treasury) revert NotTreasury();
if (newTreasury == address(0)) revert ZeroAddress();
emit TreasuryTransferred(treasury, newTreasury);
treasury = newTreasury;
}
/// @notice Claim accumulated rewards.
/// @dev Living agents claim ongoing rewards. Dead agents claim what they earned before death.
function claim() external nonReentrant {
Agent storage a = agents[msg.sender];
if (a.birthEpoch == 0) revert NotRegistered();
uint256 payout;
if (a.alive) {
uint256 _acc = accRewardPerAge;
uint256 age;
unchecked {
age = uint256(a.lastHeartbeatEpoch) - uint256(a.birthEpoch) + 1;
}
payout = (age * _acc / PRECISION) - a.rewardDebt + a.claimable;
a.rewardDebt = (age * _acc) / PRECISION;
} else {
payout = a.claimable;
}
// Effects before interaction
a.claimable = 0;
if (payout == 0) revert NothingToClaim();
unchecked { a.totalClaimed += uint128(payout); }
emit Claimed(msg.sender, payout);
// Interaction last
usdc.safeTransfer(msg.sender, payout);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_safeTransfer(token, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
if (!_safeTransferFrom(token, from, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _safeTransfer(token, to, value, false);
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _safeTransferFrom(token, from, to, value, false);
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
if (!_safeApprove(token, spender, value, false)) {
if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that relies on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Oppositely, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
* return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.transfer.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(to, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
/**
* @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
* value: the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param from The sender of the tokens
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value,
bool bubble
) private returns (bool success) {
bytes4 selector = IERC20.transferFrom.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(from, shr(96, not(0))))
mstore(0x24, and(to, shr(96, not(0))))
mstore(0x44, value)
success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
mstore(0x60, 0)
}
}
/**
* @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
* the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param spender The spender of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.approve.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(spender, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced
* by the {ReentrancyGuardTransient} variant in v6.0.
*
* @custom:stateless
*/
abstract contract ReentrancyGuard {
using StorageSlot for bytes32;
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant REENTRANCY_GUARD_STORAGE =
0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
/**
* @dev A `view` only version of {nonReentrant}. Use to block view functions
* from being called, preventing reading from inconsistent contract state.
*
* CAUTION: This is a "view" modifier and does not change the reentrancy
* status. Use it only on view functions. For payable or non-payable functions,
* use the standard {nonReentrant} modifier instead.
*/
modifier nonReentrantView() {
_nonReentrantBeforeView();
_;
}
function _nonReentrantBeforeView() private view {
if (_reentrancyGuardEntered()) {
revert ReentrancyGuardReentrantCall();
}
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
_nonReentrantBeforeView();
// Any calls to nonReentrant after this point will fail
_reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
}
function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
return REENTRANCY_GUARD_STORAGE;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_usdc","type":"address"},{"internalType":"address","name":"_identityRegistry","type":"address"},{"internalType":"uint256","name":"_epochDuration","type":"uint256"},{"internalType":"uint256","name":"_costPerEpoch","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AgentIdTaken","type":"error"},{"inputs":[],"name":"AlreadyDead","type":"error"},{"inputs":[],"name":"AlreadyHeartbeat","type":"error"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[],"name":"InvalidConfig","type":"error"},{"inputs":[],"name":"InvalidRange","type":"error"},{"inputs":[],"name":"MissedEpoch","type":"error"},{"inputs":[],"name":"NotAgentWallet","type":"error"},{"inputs":[],"name":"NotDeadYet","type":"error"},{"inputs":[],"name":"NotRegistered","type":"error"},{"inputs":[],"name":"NotTreasury","type":"error"},{"inputs":[],"name":"NothingToClaim","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":true,"internalType":"uint256","name":"agentId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"Born","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":true,"internalType":"uint256","name":"agentId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"age","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPaid","type":"uint256"}],"name":"Death","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agent","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"age","type":"uint256"}],"name":"Heartbeat","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"treasury","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TreasuryClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryTransferred","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COST_PER_EPOCH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EPOCH_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardPerAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"agentIdToAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"agents","outputs":[{"internalType":"uint64","name":"birthEpoch","type":"uint64"},{"internalType":"uint64","name":"lastHeartbeatEpoch","type":"uint64"},{"internalType":"bool","name":"alive","type":"bool"},{"internalType":"uint96","name":"totalPaid","type":"uint96"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint128","name":"claimable","type":"uint128"},{"internalType":"uint128","name":"totalClaimed","type":"uint128"},{"internalType":"uint256","name":"agentId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"getAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"getAgentList","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"agentId","type":"uint256"},{"internalType":"uint64","name":"birthEpoch","type":"uint64"},{"internalType":"uint64","name":"lastHeartbeatEpoch","type":"uint64"},{"internalType":"bool","name":"alive","type":"bool"},{"internalType":"bool","name":"killable","type":"bool"},{"internalType":"uint256","name":"age","type":"uint256"},{"internalType":"uint256","name":"totalPaid","type":"uint256"},{"internalType":"uint256","name":"totalClaimed","type":"uint256"},{"internalType":"uint256","name":"pendingReward","type":"uint256"}],"internalType":"struct LastAIStanding.AgentInfo[]","name":"agentList","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"getKillable","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"heartbeat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"identityRegistry","outputs":[{"internalType":"contract IERC8004","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAlive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isKillable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"agentId","type":"uint256"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"registryAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAlive","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDead","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEverRegistered","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardsDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"transferTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61010060405234801562000011575f80fd5b5060405162003b5938038062003b5983398181016040528101906200003791906200034a565b6001620000596200004d6200027b60201b60201c565b620002a460201b60201c565b5f01819055505f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603620000c5576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036200012b576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f820362000165576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8114806200018157506bffffffffffffffffffffffff801681115b15620001b9576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508273ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250508160c081815250508060e081815250503360065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050620003b9565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005f1b905090565b5f819050919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620002dc82620002b1565b9050919050565b620002ee81620002d0565b8114620002f9575f80fd5b50565b5f815190506200030c81620002e3565b92915050565b5f819050919050565b620003268162000312565b811462000331575f80fd5b50565b5f8151905062000344816200031b565b92915050565b5f805f8060808587031215620003655762000364620002ad565b5b5f6200037487828801620002fc565b94505060206200038787828801620002fc565b93505060406200039a8782880162000334565b9250506060620003ad8782880162000334565b91505092959194509250565b60805160a05160c05160e051613711620004485f395f8181610ba101528181610bda01528181610d8f01528181611965015281816124b7015281816124f001526128fa01525f81816119f30152611a2a01525f818161081d01526121ab01525f81816107c601528181610db001528181610e0a015281816114af015281816120e9015261291b01526137115ff3fe608060405234801561000f575f80fd5b5060043610610203575f3560e01c80636b03ec3611610118578063d8a6021c116100ab578063ee1725461161007a578063ee172546146105bd578063f207564e146105db578063f2167f41146105f7578063f40f0f5214610615578063fd66091e1461064557610203565b8063d8a6021c14610547578063e1a4521814610563578063e3cde5d514610581578063ecfb49a31461059f57610203565b8063aaf5eb68116100e7578063aaf5eb68146104bf578063c1c55d0c146104dd578063c441049d1461050d578063cbf0b0c01461052b57610203565b80636b03ec36146104355780637667180814610465578063a61f755714610483578063a70b9f0c146104a157610203565b80633e413bee1161019b5780634e71d92d1161016a5780634e71d92d1461038f57806352669b0b146103995780635893253c146103c9578063607af392146103f957806361d027b31461041757610203565b80633e413bee146102f357806345f60b431461031157806346aecff0146103415780634c25d1971461037157610203565b806318e7c3c0116101d757806318e7c3c01461027d578063313dab201461029b57806338451598146102b95780633defb962146102e957610203565b80623bdc741461020757806304c559fd14610211578063134e18f41461022f5780631703e5f91461024d575b5f80fd5b61020f61067c565b005b610219610815565b6040516102269190612e9b565b60405180910390f35b61023761081b565b6040516102449190612f2e565b60405180910390f35b61026760048036038101906102629190612f86565b61083f565b6040516102749190612fcb565b60405180910390f35b6102856108d5565b6040516102929190612e9b565b60405180910390f35b6102a36108e1565b6040516102b09190612e9b565b60405180910390f35b6102d360048036038101906102ce9190612f86565b6108e7565b6040516102e09190612e9b565b60405180910390f35b6102f1610997565b005b6102fb610e08565b6040516103089190613004565b60405180910390f35b61032b60048036038101906103269190613047565b610e2c565b604051610338919061313c565b60405180910390f35b61035b6004803603810190610356919061315c565b61117f565b6040516103689190613196565b60405180910390f35b6103796111af565b6040516103869190612e9b565b60405180910390f35b6103976111b5565b005b6103b360048036038101906103ae9190613047565b6114ff565b6040516103c09190613362565b60405180910390f35b6103e360048036038101906103de919061315c565b611928565b6040516103f09190613196565b60405180910390f35b610401611963565b60405161040e9190612e9b565b60405180910390f35b61041f611987565b60405161042c9190613196565b60405180910390f35b61044f600480360381019061044a919061315c565b6119ac565b60405161045c9190613196565b60405180910390f35b61046d6119f0565b60405161047a9190612e9b565b60405180910390f35b61048b611a22565b6040516104989190612e9b565b60405180910390f35b6104a9611a28565b6040516104b69190612e9b565b60405180910390f35b6104c7611a4c565b6040516104d49190612e9b565b60405180910390f35b6104f760048036038101906104f29190612f86565b611a58565b6040516105049190612fcb565b60405180910390f35b610515611aed565b6040516105229190613391565b60405180910390f35b61054560048036038101906105409190612f86565b611b06565b005b610561600480360381019061055c9190612f86565b611f1d565b005b61056b6120c6565b6040516105789190612e9b565b60405180910390f35b6105896120cc565b6040516105969190613391565b60405180910390f35b6105a76120e6565b6040516105b49190612e9b565b60405180910390f35b6105c5612184565b6040516105d29190612e9b565b60405180910390f35b6105f560048036038101906105f0919061315c565b61218a565b005b6105ff612974565b60405161060c9190613391565b60405180910390f35b61062f600480360381019061062a9190612f86565b61298e565b60405161063c9190612e9b565b60405180910390f35b61065f600480360381019061065a9190612f86565b612b03565b6040516106739897969594939291906133fa565b60405180910390f35b610684612bc6565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461070a576040517fb90cdbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60075490505f8103610749576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6007819055503373ffffffffffffffffffffffffffffffffffffffff167f0dafe5fda3d3c12f5534ba82c4393aaf90fe68d6198d310d71a7d9a6ea3cc1e0826040516107969190612e9b565b60405180910390a261080a60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612be89092919063ffffffff16565b50610813612c3b565b565b60045481565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1661089d575f9150506108d0565b6001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16016108ca6119f0565b11159150505b919050565b5f600280549050905090565b60075481565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f8167ffffffffffffffff160361095c575f92505050610992565b60018167ffffffffffffffff16835f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff160301925050505b919050565b61099f612bc6565b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610a37576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0160109054906101000a900460ff16610a7e576040517fe503b2d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610a876119f0565b90505f825f0160089054906101000a900467ffffffffffffffff1690508067ffffffffffffffff168203610ae7576040517ffac6cb6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018167ffffffffffffffff1601821115610b2e576040517fc3a5335100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60055490505f6001855f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168467ffffffffffffffff16030190505f8560010154670de0b6b3a76400008484610b8291906134a3565b610b8c9190613511565b610b969190613541565b90505f6127106103e87f0000000000000000000000000000000000000000000000000000000000000000610bca91906134a3565b610bd49190613511565b90505f817f0000000000000000000000000000000000000000000000000000000000000000610c039190613541565b90508160075f828254610c169190613574565b9250508190555082886002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555080885f0160118282829054906101000a90046bffffffffffffffffffffffff160192506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555086885f0160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505f600185019050600160045f828254610d0a9190613574565b92505081905550670de0b6b3a76400008682610d2691906134a3565b610d309190613511565b89600101819055503373ffffffffffffffffffffffffffffffffffffffff167fd31a97f4dfb5424af58b0a502190f247d1566c430982a5a9161c61f99b91b1ac8983604051610d809291906135a7565b60405180910390a2610df533307f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612c55909392919063ffffffff16565b505050505050505050610e06612c3b565b565b7f000000000000000000000000000000000000000000000000000000000000000081565b60605f60028054905090505f8103610e8f575f67ffffffffffffffff811115610e5857610e576135ce565b5b604051908082528060200260200182016040528015610e865781602001602082028036833780820191505090505b50915050611179565b82841115610ec9576040517f561ce9bb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808310610ee057600181610edd9190613541565b92505b5f610ee96119f0565b90505f60018686030190505f805b82811015610fda575f805f6002848c610f109190613574565b81548110610f2157610f206135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1615610fce576001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1601851115610fcd578260010192505b5b81600101915050610ef7565b505f8167ffffffffffffffff811115610ff657610ff56135ce565b5b6040519080825280602002602001820160405280156110245781602001602082028036833780820191505090505b5090505f805b8481101561116e575f6002828c6110419190613574565b81548110611052576110516135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1615611161576001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16018811156111605781858581518110611111576111106135fb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505085846001019450840361115f57505061116e565b5b5b826001019250505061102a565b508196505050505050505b92915050565b6001602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6103e881565b6111bd612bc6565b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603611255576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f815f0160109054906101000a900460ff1615611356575f60055490505f6001845f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16855f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603019050836002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168460010154670de0b6b3a7640000848461130891906134a3565b6113129190613511565b61131c9190613541565b6113269190613574565b9250670de0b6b3a7640000828261133d91906134a3565b6113479190613511565b8460010181905550505061138b565b816002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1690505b5f826002015f6101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505f81036113fe576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808260020160108282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a826040516114a09190612e9b565b60405180910390a26114f333827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612be89092919063ffffffff16565b50506114fd612c3b565b565b60605f60028054905090505f810361156d575f67ffffffffffffffff81111561152b5761152a6135ce565b5b60405190808252806020026020018201604052801561156457816020015b611551612e0c565b8152602001906001900390816115495790505b50915050611922565b828411156115a7576040517f561ce9bb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8083106115be576001816115bb9190613541565b92505b5f60018585030190508067ffffffffffffffff8111156115e1576115e06135ce565b5b60405190808252806020026020018201604052801561161a57816020015b611607612e0c565b8152602001906001900390816115ff5790505b5092505f6116266119f0565b90505f60055490505f5b8381101561191c575f6002828a018154811061164f5761164e6135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f825f0160089054906101000a900467ffffffffffffffff1690505f835f0160109054906101000a900460ff1690505f8082801561171c575060018467ffffffffffffffff16018a115b91505f8567ffffffffffffffff161461174e5760018567ffffffffffffffff168567ffffffffffffffff160301611750565b5f5b90505f808667ffffffffffffffff160361176c575f9050611818565b836117aa57866002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff169050611817565b866002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168760010154670de0b6b3a76400008c856117f691906134a3565b6118009190613511565b61180a9190613541565b6118149190613574565b90505b5b6040518061014001604052808973ffffffffffffffffffffffffffffffffffffffff168152602001886003015481526020018767ffffffffffffffff1681526020018667ffffffffffffffff16815260200185151581526020018415158152602001838152602001885f0160119054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1681526020018860020160109054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001828152508e8a815181106118fe576118fd6135fb565b5b60200260200101819052508860010198505050505050505050611630565b50505050505b92915050565b60028181548110611937575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600282815481106119c1576119c06135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f7f000000000000000000000000000000000000000000000000000000000000000042611a1d9190613511565b905090565b60055481565b7f000000000000000000000000000000000000000000000000000000000000000081565b670de0b6b3a764000081565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff16611ab6575f915050611ae8565b6001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1601611ae36119f0565b119150505b919050565b60035f9054906101000a900467ffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603611b9e576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0160109054906101000a900460ff16611be5576040517fe503b2d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bee6119f0565b90505f825f0160089054906101000a900467ffffffffffffffff16905060018167ffffffffffffffff16018211611c51576040517f3213d1a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6001845f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168367ffffffffffffffff16030190505f60055490505f8560010154670de0b6b3a76400008385611ca591906134a3565b611caf9190613511565b611cb99190613541565b905080866002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505f86600101819055505f865f0160106101000a81548160ff02191690831515021790555060035f81819054906101000a900467ffffffffffffffff16809291906001900391906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550506003600881819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508260045f828254611dd99190613541565b925050819055505f865f0160119054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1690505f60045490505f811115611e505780670de0b6b3a764000083611e3091906134a3565b611e3a9190613511565b84611e459190613574565b600581905550611eac565b81886002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b8160085f828254019250508190555087600301548973ffffffffffffffffffffffffffffffffffffffff167fa56d5cc0fe722918425eb7b68f147546cfdc6664d22823d16f60797fb9a2ba6d898886604051611f0a93929190613628565b60405180910390a3505050505050505050565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611fa3576040517fb90cdbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612008576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febebcc22237fa047dcfebf54b185ec126c9b24d45f4bd2a18e4fa02e07308c4060405160405180910390a38060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61271081565b600360109054906101000a900467ffffffffffffffff1681565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016121409190613196565b602060405180830381865afa15801561215b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217f9190613671565b905090565b60085481565b612192612bc6565b3373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1662339509836040518263ffffffff1660e01b81526004016122019190612e9b565b602060405180830381865afa15801561221c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061224091906136b0565b73ffffffffffffffffffffffffffffffffffffffff161461228d576040517f93538e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561232957503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15612360576040517f5aabd57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff16156123e7576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80825f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff161490508015801561241f575083826003015414155b15612456576040517f5aabd57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61245f6119f0565b90505f836002015f9054906101000a90046fffffffffffffffffffffffffffffffff1690505f8460020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505f60055490505f6127106103e87f00000000000000000000000000000000000000000000000000000000000000006124e091906134a3565b6124ea9190613511565b90505f817f00000000000000000000000000000000000000000000000000000000000000006125199190613541565b90508160075f82825461252c9190613574565b925050819055506040518061010001604052808767ffffffffffffffff1681526020018767ffffffffffffffff168152602001600115158152602001826bffffffffffffffffffffffff168152602001670de0b6b3a7640000856125909190613511565b8152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018b8152505f803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506020820151815f0160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506040820151815f0160106101000a81548160ff0219169083151502179055506060820151815f0160116101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506080820151816001015560a0820151816002015f6101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160020160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060e0820151816003015590505086156127fe573360015f8c81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600233908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60035f81819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550506003601081819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050600160045f82825461289d9190613574565b92505081905550893373ffffffffffffffffffffffffffffffffffffffff167f5d8504ca0acefa24e159e93b4920c8053bee527ed26781bccef37f391fb0533f886040516128eb9190612e9b565b60405180910390a361296033307f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16612c55909392919063ffffffff16565b505050505050505050612971612c3b565b50565b600360089054906101000a900467ffffffffffffffff1681565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f8167ffffffffffffffff1603612a03575f92505050612afe565b815f0160109054906101000a900460ff16612a5357816002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1692505050612afe565b5f60055490505f60018367ffffffffffffffff16855f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603019050836002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168460010154670de0b6b3a76400008484612ad991906134a3565b612ae39190613511565b612aed9190613541565b612af79190613574565b9450505050505b919050565b5f602052805f5260405f205f91509050805f015f9054906101000a900467ffffffffffffffff1690805f0160089054906101000a900467ffffffffffffffff1690805f0160109054906101000a900460ff1690805f0160119054906101000a90046bffffffffffffffffffffffff1690806001015490806002015f9054906101000a90046fffffffffffffffffffffffffffffffff16908060020160109054906101000a90046fffffffffffffffffffffffffffffffff16908060030154905088565b612bce612caa565b6002612be0612bdb612ceb565b612d14565b5f0181905550565b612bf58383836001612d1d565b612c3657826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401612c2d9190613196565b60405180910390fd5b505050565b6001612c4d612c48612ceb565b612d14565b5f0181905550565b612c63848484846001612d7f565b612ca457836040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401612c9b9190613196565b60405180910390fd5b50505050565b612cb2612df0565b15612ce9576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005f1b905090565b5f819050919050565b5f8063a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f808b5af1925060015f51148316612d71578383151615612d65573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b5f806323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f808c5af1925060015f51148316612ddd578383151615612dd1573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b5f6002612e03612dfe612ceb565b612d14565b5f015414905090565b6040518061014001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81526020015f67ffffffffffffffff1681526020015f67ffffffffffffffff1681526020015f151581526020015f151581526020015f81526020015f81526020015f81526020015f81525090565b5f819050919050565b612e9581612e83565b82525050565b5f602082019050612eae5f830184612e8c565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f612ef6612ef1612eec84612eb4565b612ed3565b612eb4565b9050919050565b5f612f0782612edc565b9050919050565b5f612f1882612efd565b9050919050565b612f2881612f0e565b82525050565b5f602082019050612f415f830184612f1f565b92915050565b5f80fd5b5f612f5582612eb4565b9050919050565b612f6581612f4b565b8114612f6f575f80fd5b50565b5f81359050612f8081612f5c565b92915050565b5f60208284031215612f9b57612f9a612f47565b5b5f612fa884828501612f72565b91505092915050565b5f8115159050919050565b612fc581612fb1565b82525050565b5f602082019050612fde5f830184612fbc565b92915050565b5f612fee82612efd565b9050919050565b612ffe81612fe4565b82525050565b5f6020820190506130175f830184612ff5565b92915050565b61302681612e83565b8114613030575f80fd5b50565b5f813590506130418161301d565b92915050565b5f806040838503121561305d5761305c612f47565b5b5f61306a85828601613033565b925050602061307b85828601613033565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6130b781612f4b565b82525050565b5f6130c883836130ae565b60208301905092915050565b5f602082019050919050565b5f6130ea82613085565b6130f4818561308f565b93506130ff8361309f565b805f5b8381101561312f57815161311688826130bd565b9750613121836130d4565b925050600181019050613102565b5085935050505092915050565b5f6020820190508181035f83015261315481846130e0565b905092915050565b5f6020828403121561317157613170612f47565b5b5f61317e84828501613033565b91505092915050565b61319081612f4b565b82525050565b5f6020820190506131a95f830184613187565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6131e181612e83565b82525050565b5f67ffffffffffffffff82169050919050565b613203816131e7565b82525050565b61321281612fb1565b82525050565b61014082015f82015161322d5f8501826130ae565b50602082015161324060208501826131d8565b50604082015161325360408501826131fa565b50606082015161326660608501826131fa565b5060808201516132796080850182613209565b5060a082015161328c60a0850182613209565b5060c082015161329f60c08501826131d8565b5060e08201516132b260e08501826131d8565b506101008201516132c76101008501826131d8565b506101208201516132dc6101208501826131d8565b50505050565b5f6132ed8383613218565b6101408301905092915050565b5f602082019050919050565b5f613310826131af565b61331a81856131b9565b9350613325836131c9565b805f5b8381101561335557815161333c88826132e2565b9750613347836132fa565b925050600181019050613328565b5085935050505092915050565b5f6020820190508181035f83015261337a8184613306565b905092915050565b61338b816131e7565b82525050565b5f6020820190506133a45f830184613382565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b6133ca816133aa565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b6133f4816133d0565b82525050565b5f6101008201905061340e5f83018b613382565b61341b602083018a613382565b6134286040830189612fbc565b61343560608301886133c1565b6134426080830187612e8c565b61344f60a08301866133eb565b61345c60c08301856133eb565b61346960e0830184612e8c565b9998505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6134ad82612e83565b91506134b883612e83565b92508282026134c681612e83565b915082820484148315176134dd576134dc613476565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61351b82612e83565b915061352683612e83565b925082613536576135356134e4565b5b828204905092915050565b5f61354b82612e83565b915061355683612e83565b925082820390508181111561356e5761356d613476565b5b92915050565b5f61357e82612e83565b915061358983612e83565b92508282019050808211156135a1576135a0613476565b5b92915050565b5f6040820190506135ba5f830185612e8c565b6135c76020830184612e8c565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60608201905061363b5f830186612e8c565b6136486020830185612e8c565b6136556040830184612e8c565b949350505050565b5f8151905061366b8161301d565b92915050565b5f6020828403121561368657613685612f47565b5b5f6136938482850161365d565b91505092915050565b5f815190506136aa81612f5c565b92915050565b5f602082840312156136c5576136c4612f47565b5b5f6136d28482850161369c565b9150509291505056fea264697066735822122054c74d8e99a147ef1c5a70ddbb2da9c188fdfbdab2a2b995aef7c6e12a2bb77d64736f6c63430008180033000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000008004a169fb4a3325136eb29fa0ceb6d2e539a432000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000000186a0
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610203575f3560e01c80636b03ec3611610118578063d8a6021c116100ab578063ee1725461161007a578063ee172546146105bd578063f207564e146105db578063f2167f41146105f7578063f40f0f5214610615578063fd66091e1461064557610203565b8063d8a6021c14610547578063e1a4521814610563578063e3cde5d514610581578063ecfb49a31461059f57610203565b8063aaf5eb68116100e7578063aaf5eb68146104bf578063c1c55d0c146104dd578063c441049d1461050d578063cbf0b0c01461052b57610203565b80636b03ec36146104355780637667180814610465578063a61f755714610483578063a70b9f0c146104a157610203565b80633e413bee1161019b5780634e71d92d1161016a5780634e71d92d1461038f57806352669b0b146103995780635893253c146103c9578063607af392146103f957806361d027b31461041757610203565b80633e413bee146102f357806345f60b431461031157806346aecff0146103415780634c25d1971461037157610203565b806318e7c3c0116101d757806318e7c3c01461027d578063313dab201461029b57806338451598146102b95780633defb962146102e957610203565b80623bdc741461020757806304c559fd14610211578063134e18f41461022f5780631703e5f91461024d575b5f80fd5b61020f61067c565b005b610219610815565b6040516102269190612e9b565b60405180910390f35b61023761081b565b6040516102449190612f2e565b60405180910390f35b61026760048036038101906102629190612f86565b61083f565b6040516102749190612fcb565b60405180910390f35b6102856108d5565b6040516102929190612e9b565b60405180910390f35b6102a36108e1565b6040516102b09190612e9b565b60405180910390f35b6102d360048036038101906102ce9190612f86565b6108e7565b6040516102e09190612e9b565b60405180910390f35b6102f1610997565b005b6102fb610e08565b6040516103089190613004565b60405180910390f35b61032b60048036038101906103269190613047565b610e2c565b604051610338919061313c565b60405180910390f35b61035b6004803603810190610356919061315c565b61117f565b6040516103689190613196565b60405180910390f35b6103796111af565b6040516103869190612e9b565b60405180910390f35b6103976111b5565b005b6103b360048036038101906103ae9190613047565b6114ff565b6040516103c09190613362565b60405180910390f35b6103e360048036038101906103de919061315c565b611928565b6040516103f09190613196565b60405180910390f35b610401611963565b60405161040e9190612e9b565b60405180910390f35b61041f611987565b60405161042c9190613196565b60405180910390f35b61044f600480360381019061044a919061315c565b6119ac565b60405161045c9190613196565b60405180910390f35b61046d6119f0565b60405161047a9190612e9b565b60405180910390f35b61048b611a22565b6040516104989190612e9b565b60405180910390f35b6104a9611a28565b6040516104b69190612e9b565b60405180910390f35b6104c7611a4c565b6040516104d49190612e9b565b60405180910390f35b6104f760048036038101906104f29190612f86565b611a58565b6040516105049190612fcb565b60405180910390f35b610515611aed565b6040516105229190613391565b60405180910390f35b61054560048036038101906105409190612f86565b611b06565b005b610561600480360381019061055c9190612f86565b611f1d565b005b61056b6120c6565b6040516105789190612e9b565b60405180910390f35b6105896120cc565b6040516105969190613391565b60405180910390f35b6105a76120e6565b6040516105b49190612e9b565b60405180910390f35b6105c5612184565b6040516105d29190612e9b565b60405180910390f35b6105f560048036038101906105f0919061315c565b61218a565b005b6105ff612974565b60405161060c9190613391565b60405180910390f35b61062f600480360381019061062a9190612f86565b61298e565b60405161063c9190612e9b565b60405180910390f35b61065f600480360381019061065a9190612f86565b612b03565b6040516106739897969594939291906133fa565b60405180910390f35b610684612bc6565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461070a576040517fb90cdbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60075490505f8103610749576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6007819055503373ffffffffffffffffffffffffffffffffffffffff167f0dafe5fda3d3c12f5534ba82c4393aaf90fe68d6198d310d71a7d9a6ea3cc1e0826040516107969190612e9b565b60405180910390a261080a60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16827f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291373ffffffffffffffffffffffffffffffffffffffff16612be89092919063ffffffff16565b50610813612c3b565b565b60045481565b7f0000000000000000000000008004a169fb4a3325136eb29fa0ceb6d2e539a43281565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1661089d575f9150506108d0565b6001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16016108ca6119f0565b11159150505b919050565b5f600280549050905090565b60075481565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f8167ffffffffffffffff160361095c575f92505050610992565b60018167ffffffffffffffff16835f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff160301925050505b919050565b61099f612bc6565b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610a37576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0160109054906101000a900460ff16610a7e576040517fe503b2d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610a876119f0565b90505f825f0160089054906101000a900467ffffffffffffffff1690508067ffffffffffffffff168203610ae7576040517ffac6cb6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018167ffffffffffffffff1601821115610b2e576040517fc3a5335100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60055490505f6001855f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168467ffffffffffffffff16030190505f8560010154670de0b6b3a76400008484610b8291906134a3565b610b8c9190613511565b610b969190613541565b90505f6127106103e87f00000000000000000000000000000000000000000000000000000000000186a0610bca91906134a3565b610bd49190613511565b90505f817f00000000000000000000000000000000000000000000000000000000000186a0610c039190613541565b90508160075f828254610c169190613574565b9250508190555082886002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555080885f0160118282829054906101000a90046bffffffffffffffffffffffff160192506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555086885f0160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505f600185019050600160045f828254610d0a9190613574565b92505081905550670de0b6b3a76400008682610d2691906134a3565b610d309190613511565b89600101819055503373ffffffffffffffffffffffffffffffffffffffff167fd31a97f4dfb5424af58b0a502190f247d1566c430982a5a9161c61f99b91b1ac8983604051610d809291906135a7565b60405180910390a2610df533307f00000000000000000000000000000000000000000000000000000000000186a07f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291373ffffffffffffffffffffffffffffffffffffffff16612c55909392919063ffffffff16565b505050505050505050610e06612c3b565b565b7f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291381565b60605f60028054905090505f8103610e8f575f67ffffffffffffffff811115610e5857610e576135ce565b5b604051908082528060200260200182016040528015610e865781602001602082028036833780820191505090505b50915050611179565b82841115610ec9576040517f561ce9bb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808310610ee057600181610edd9190613541565b92505b5f610ee96119f0565b90505f60018686030190505f805b82811015610fda575f805f6002848c610f109190613574565b81548110610f2157610f206135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1615610fce576001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1601851115610fcd578260010192505b5b81600101915050610ef7565b505f8167ffffffffffffffff811115610ff657610ff56135ce565b5b6040519080825280602002602001820160405280156110245781602001602082028036833780820191505090505b5090505f805b8481101561116e575f6002828c6110419190613574565b81548110611052576110516135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff1615611161576001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16018811156111605781858581518110611111576111106135fb565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505085846001019450840361115f57505061116e565b5b5b826001019250505061102a565b508196505050505050505b92915050565b6001602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6103e881565b6111bd612bc6565b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603611255576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f815f0160109054906101000a900460ff1615611356575f60055490505f6001845f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16855f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603019050836002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168460010154670de0b6b3a7640000848461130891906134a3565b6113129190613511565b61131c9190613541565b6113269190613574565b9250670de0b6b3a7640000828261133d91906134a3565b6113479190613511565b8460010181905550505061138b565b816002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1690505b5f826002015f6101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505f81036113fe576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808260020160108282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a826040516114a09190612e9b565b60405180910390a26114f333827f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291373ffffffffffffffffffffffffffffffffffffffff16612be89092919063ffffffff16565b50506114fd612c3b565b565b60605f60028054905090505f810361156d575f67ffffffffffffffff81111561152b5761152a6135ce565b5b60405190808252806020026020018201604052801561156457816020015b611551612e0c565b8152602001906001900390816115495790505b50915050611922565b828411156115a7576040517f561ce9bb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8083106115be576001816115bb9190613541565b92505b5f60018585030190508067ffffffffffffffff8111156115e1576115e06135ce565b5b60405190808252806020026020018201604052801561161a57816020015b611607612e0c565b8152602001906001900390816115ff5790505b5092505f6116266119f0565b90505f60055490505f5b8381101561191c575f6002828a018154811061164f5761164e6135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f825f0160089054906101000a900467ffffffffffffffff1690505f835f0160109054906101000a900460ff1690505f8082801561171c575060018467ffffffffffffffff16018a115b91505f8567ffffffffffffffff161461174e5760018567ffffffffffffffff168567ffffffffffffffff160301611750565b5f5b90505f808667ffffffffffffffff160361176c575f9050611818565b836117aa57866002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff169050611817565b866002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168760010154670de0b6b3a76400008c856117f691906134a3565b6118009190613511565b61180a9190613541565b6118149190613574565b90505b5b6040518061014001604052808973ffffffffffffffffffffffffffffffffffffffff168152602001886003015481526020018767ffffffffffffffff1681526020018667ffffffffffffffff16815260200185151581526020018415158152602001838152602001885f0160119054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1681526020018860020160109054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001828152508e8a815181106118fe576118fd6135fb565b5b60200260200101819052508860010198505050505050505050611630565b50505050505b92915050565b60028181548110611937575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000186a081565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f600282815481106119c1576119c06135fb565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f7f000000000000000000000000000000000000000000000000000000000000025842611a1d9190613511565b905090565b60055481565b7f000000000000000000000000000000000000000000000000000000000000025881565b670de0b6b3a764000081565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff16611ab6575f915050611ae8565b6001815f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1601611ae36119f0565b119150505b919050565b60035f9054906101000a900467ffffffffffffffff1681565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff1603611b9e576040517faba4733900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f0160109054906101000a900460ff16611be5576040517fe503b2d600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bee6119f0565b90505f825f0160089054906101000a900467ffffffffffffffff16905060018167ffffffffffffffff16018211611c51576040517f3213d1a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6001845f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff168367ffffffffffffffff16030190505f60055490505f8560010154670de0b6b3a76400008385611ca591906134a3565b611caf9190613511565b611cb99190613541565b905080866002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505f86600101819055505f865f0160106101000a81548160ff02191690831515021790555060035f81819054906101000a900467ffffffffffffffff16809291906001900391906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550506003600881819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508260045f828254611dd99190613541565b925050819055505f865f0160119054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1690505f60045490505f811115611e505780670de0b6b3a764000083611e3091906134a3565b611e3a9190613511565b84611e459190613574565b600581905550611eac565b81886002015f8282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b8160085f828254019250508190555087600301548973ffffffffffffffffffffffffffffffffffffffff167fa56d5cc0fe722918425eb7b68f147546cfdc6664d22823d16f60797fb9a2ba6d898886604051611f0a93929190613628565b60405180910390a3505050505050505050565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611fa3576040517fb90cdbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612008576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febebcc22237fa047dcfebf54b185ec126c9b24d45f4bd2a18e4fa02e07308c4060405160405180910390a38060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61271081565b600360109054906101000a900467ffffffffffffffff1681565b5f7f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016121409190613196565b602060405180830381865afa15801561215b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217f9190613671565b905090565b60085481565b612192612bc6565b3373ffffffffffffffffffffffffffffffffffffffff167f0000000000000000000000008004a169fb4a3325136eb29fa0ceb6d2e539a43273ffffffffffffffffffffffffffffffffffffffff1662339509836040518263ffffffff1660e01b81526004016122019190612e9b565b602060405180830381865afa15801561221c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061224091906136b0565b73ffffffffffffffffffffffffffffffffffffffff161461228d576040517f93538e0000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60015f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561232957503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15612360576040517f5aabd57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f209050805f0160109054906101000a900460ff16156123e7576040517f3a81d6fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80825f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff161490508015801561241f575083826003015414155b15612456576040517f5aabd57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61245f6119f0565b90505f836002015f9054906101000a90046fffffffffffffffffffffffffffffffff1690505f8460020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505f60055490505f6127106103e87f00000000000000000000000000000000000000000000000000000000000186a06124e091906134a3565b6124ea9190613511565b90505f817f00000000000000000000000000000000000000000000000000000000000186a06125199190613541565b90508160075f82825461252c9190613574565b925050819055506040518061010001604052808767ffffffffffffffff1681526020018767ffffffffffffffff168152602001600115158152602001826bffffffffffffffffffffffff168152602001670de0b6b3a7640000856125909190613511565b8152602001866fffffffffffffffffffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff1681526020018b8152505f803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506020820151815f0160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506040820151815f0160106101000a81548160ff0219169083151502179055506060820151815f0160116101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055506080820151816001015560a0820151816002015f6101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160020160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060e0820151816003015590505086156127fe573360015f8c81526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600233908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60035f81819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550506003601081819054906101000a900467ffffffffffffffff168092919060010191906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050600160045f82825461289d9190613574565b92505081905550893373ffffffffffffffffffffffffffffffffffffffff167f5d8504ca0acefa24e159e93b4920c8053bee527ed26781bccef37f391fb0533f886040516128eb9190612e9b565b60405180910390a361296033307f00000000000000000000000000000000000000000000000000000000000186a07f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291373ffffffffffffffffffffffffffffffffffffffff16612c55909392919063ffffffff16565b505050505050505050612971612c3b565b50565b600360089054906101000a900467ffffffffffffffff1681565b5f805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2090505f815f015f9054906101000a900467ffffffffffffffff1690505f8167ffffffffffffffff1603612a03575f92505050612afe565b815f0160109054906101000a900460ff16612a5357816002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1692505050612afe565b5f60055490505f60018367ffffffffffffffff16855f0160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603019050836002015f9054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168460010154670de0b6b3a76400008484612ad991906134a3565b612ae39190613511565b612aed9190613541565b612af79190613574565b9450505050505b919050565b5f602052805f5260405f205f91509050805f015f9054906101000a900467ffffffffffffffff1690805f0160089054906101000a900467ffffffffffffffff1690805f0160109054906101000a900460ff1690805f0160119054906101000a90046bffffffffffffffffffffffff1690806001015490806002015f9054906101000a90046fffffffffffffffffffffffffffffffff16908060020160109054906101000a90046fffffffffffffffffffffffffffffffff16908060030154905088565b612bce612caa565b6002612be0612bdb612ceb565b612d14565b5f0181905550565b612bf58383836001612d1d565b612c3657826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401612c2d9190613196565b60405180910390fd5b505050565b6001612c4d612c48612ceb565b612d14565b5f0181905550565b612c63848484846001612d7f565b612ca457836040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401612c9b9190613196565b60405180910390fd5b50505050565b612cb2612df0565b15612ce9576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005f1b905090565b5f819050919050565b5f8063a9059cbb60e01b9050604051815f525f1960601c86166004528460245260205f60445f808b5af1925060015f51148316612d71578383151615612d65573d5f823e3d81fd5b5f873b113d1516831692505b806040525050949350505050565b5f806323b872dd60e01b9050604051815f525f1960601c87166004525f1960601c86166024528460445260205f60645f808c5af1925060015f51148316612ddd578383151615612dd1573d5f823e3d81fd5b5f883b113d1516831692505b806040525f606052505095945050505050565b5f6002612e03612dfe612ceb565b612d14565b5f015414905090565b6040518061014001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81526020015f67ffffffffffffffff1681526020015f67ffffffffffffffff1681526020015f151581526020015f151581526020015f81526020015f81526020015f81526020015f81525090565b5f819050919050565b612e9581612e83565b82525050565b5f602082019050612eae5f830184612e8c565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f612ef6612ef1612eec84612eb4565b612ed3565b612eb4565b9050919050565b5f612f0782612edc565b9050919050565b5f612f1882612efd565b9050919050565b612f2881612f0e565b82525050565b5f602082019050612f415f830184612f1f565b92915050565b5f80fd5b5f612f5582612eb4565b9050919050565b612f6581612f4b565b8114612f6f575f80fd5b50565b5f81359050612f8081612f5c565b92915050565b5f60208284031215612f9b57612f9a612f47565b5b5f612fa884828501612f72565b91505092915050565b5f8115159050919050565b612fc581612fb1565b82525050565b5f602082019050612fde5f830184612fbc565b92915050565b5f612fee82612efd565b9050919050565b612ffe81612fe4565b82525050565b5f6020820190506130175f830184612ff5565b92915050565b61302681612e83565b8114613030575f80fd5b50565b5f813590506130418161301d565b92915050565b5f806040838503121561305d5761305c612f47565b5b5f61306a85828601613033565b925050602061307b85828601613033565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6130b781612f4b565b82525050565b5f6130c883836130ae565b60208301905092915050565b5f602082019050919050565b5f6130ea82613085565b6130f4818561308f565b93506130ff8361309f565b805f5b8381101561312f57815161311688826130bd565b9750613121836130d4565b925050600181019050613102565b5085935050505092915050565b5f6020820190508181035f83015261315481846130e0565b905092915050565b5f6020828403121561317157613170612f47565b5b5f61317e84828501613033565b91505092915050565b61319081612f4b565b82525050565b5f6020820190506131a95f830184613187565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b6131e181612e83565b82525050565b5f67ffffffffffffffff82169050919050565b613203816131e7565b82525050565b61321281612fb1565b82525050565b61014082015f82015161322d5f8501826130ae565b50602082015161324060208501826131d8565b50604082015161325360408501826131fa565b50606082015161326660608501826131fa565b5060808201516132796080850182613209565b5060a082015161328c60a0850182613209565b5060c082015161329f60c08501826131d8565b5060e08201516132b260e08501826131d8565b506101008201516132c76101008501826131d8565b506101208201516132dc6101208501826131d8565b50505050565b5f6132ed8383613218565b6101408301905092915050565b5f602082019050919050565b5f613310826131af565b61331a81856131b9565b9350613325836131c9565b805f5b8381101561335557815161333c88826132e2565b9750613347836132fa565b925050600181019050613328565b5085935050505092915050565b5f6020820190508181035f83015261337a8184613306565b905092915050565b61338b816131e7565b82525050565b5f6020820190506133a45f830184613382565b92915050565b5f6bffffffffffffffffffffffff82169050919050565b6133ca816133aa565b82525050565b5f6fffffffffffffffffffffffffffffffff82169050919050565b6133f4816133d0565b82525050565b5f6101008201905061340e5f83018b613382565b61341b602083018a613382565b6134286040830189612fbc565b61343560608301886133c1565b6134426080830187612e8c565b61344f60a08301866133eb565b61345c60c08301856133eb565b61346960e0830184612e8c565b9998505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6134ad82612e83565b91506134b883612e83565b92508282026134c681612e83565b915082820484148315176134dd576134dc613476565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61351b82612e83565b915061352683612e83565b925082613536576135356134e4565b5b828204905092915050565b5f61354b82612e83565b915061355683612e83565b925082820390508181111561356e5761356d613476565b5b92915050565b5f61357e82612e83565b915061358983612e83565b92508282019050808211156135a1576135a0613476565b5b92915050565b5f6040820190506135ba5f830185612e8c565b6135c76020830184612e8c565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60608201905061363b5f830186612e8c565b6136486020830185612e8c565b6136556040830184612e8c565b949350505050565b5f8151905061366b8161301d565b92915050565b5f6020828403121561368657613685612f47565b5b5f6136938482850161365d565b91505092915050565b5f815190506136aa81612f5c565b92915050565b5f602082840312156136c5576136c4612f47565b5b5f6136d28482850161369c565b9150509291505056fea264697066735822122054c74d8e99a147ef1c5a70ddbb2da9c188fdfbdab2a2b995aef7c6e12a2bb77d64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000008004a169fb4a3325136eb29fa0ceb6d2e539a432000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000000186a0
-----Decoded View---------------
Arg [0] : _usdc (address): 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Arg [1] : _identityRegistry (address): 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
Arg [2] : _epochDuration (uint256): 600
Arg [3] : _costPerEpoch (uint256): 100000
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913
Arg [1] : 0000000000000000000000008004a169fb4a3325136eb29fa0ceb6d2e539a432
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [3] : 00000000000000000000000000000000000000000000000000000000000186a0
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.79
Net Worth in ETH
0.00036
Token Allocations
USDC
100.00%
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BASE | 100.00% | $0.999875 | 0.7871 | $0.787 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.