019d5666-71fa-715c-bc73-4d8f84d559bb
Open this run to answer one question: is this real attacker-relevant behavior with real impact, or just normal contract plumbing?
| ID | Type | Status | Attempts | Heartbeat |
|---|---|---|---|---|
| 42827 | artifact.fetch | complete | 1 / 3 | 1 week ago |
| 42828 | proxy.resolve | complete | 1 / 3 | 1 week ago |
| 42829 | tool.cast_disasm | complete | 1 / 3 | 1 week ago |
| 42830 | analysis.bundle | complete | 1 / 3 | 1 week ago |
| 42831 | capability.graph | complete | 1 / 3 | 1 week ago |
| 42832 | detector.run | complete | 1 / 3 | 1 week ago |
| 42833 | validation.fork | complete | 1 / 3 | 1 week ago |
| 42947 | report.consolidate | complete | 1 / 6 | 1 week ago |
| 42948 | tool.slither | complete | 1 / 2 | 1 week ago |
{
"status": "not_proxy"
}
'forge clean' running (wd: /tmp/slither-b4rpb__s) 'forge config --json' running 'forge build --build-info --skip ./test/** ./script/** --force' running (wd: /tmp/slither-b4rpb__s) DividendDistributor.deposit() (contracts/external/DividendDistributor.sol#79-84) should emit an event for: - dividendsPerShare = dividendsPerShare.add(dividendsPerShareAccuracyFactor.mul(msg.value).div(totalShares)) (contracts/external/DividendDistributor.sol#81-83) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic Version constraint ^0.6.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html) - AbiReencodingHeadOverflowWithStaticArrayCleanup - DirtyBytesArrayToStorage - NestedCalldataArrayAbiReencodingSizeValidation - ABIDecodeTwoDimensionalArrayMemory - KeccakCaching - EmptyByteArrayCopy - DynamicArrayCleanup - MissingEscapingInFormatting - ArraySliceDynamicallyEncodedBaseType - ImplicitConstructorCallvalueCheck - TupleAssignmentMultiStackSlotComponents - MemoryArrayCreationOverflow - YulOptimizerRedundantAssignmentBreakContinue. It is used by: - ^0.6.0 (contracts/external/DividendDistributor.sol#2) - ^0.6.0 (contracts/external/IDividendDistributor.sol#2) - ^0.6.0 (contracts/external/IERC20.sol#2) - ^0.6.0 (contracts/external/ReentrancyGuard.sol#2) - ^0.6.0 (contracts/external/SafeMath.sol#2) solc-0.6.0 is an outdated solc version. Use a more recent version (at least 0.8.0), if possible. Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity Parameter DividendDistributor.setDistributionCriteria(uint256,uint256)._minPeriod (contracts/external/DividendDistributor.sol#49) is not in mixedCase Parameter DividendDistributor.setDistributionCriteria(uint256,uint256)._minDistribution (contracts/external/DividendDistributor.sol#50) is not in mixedCase Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions Reentrancy in DividendDistributor.distributeDividend(address) (contracts/external/DividendDistributor.sol#86-106): External calls: - shareholder.transfer(amount) (contracts/external/DividendDistributor.sol#95) State variables written after the call(s): - shareholderClaims[shareholder] = block.timestamp (contracts/external/DividendDistributor.sol#96) - shares[shareholder].totalRealised = shares[shareholder].totalRealised.add(amount) (contracts/external/DividendDistributor.sol#97-99) - shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount) (contracts/external/DividendDistributor.sol#100-102) Event emitted after the call(s): - DividendDistributed(shareholder,amount) (contracts/external/DividendDistributor.sol#104) Reentrancy in DividendDistributor.setShare(address,uint256) (contracts/external/DividendDistributor.sol#56-77): External calls: - distributeDividend(address(shareholder)) (contracts/external/DividendDistributor.sol#62) - shareholder.transfer(amount) (contracts/external/DividendDistributor.sol#95) State variables written after the call(s): - addShareholder(shareholder) (contracts/external/DividendDistributor.sol#66) - shareholderIndexes[shareholder] = shareholders.length (contracts/external/DividendDistributor.sol#143) - removeShareholder(shareholder) (contracts/external/DividendDistributor.sol#68) - shareholderIndexes[shareholders[shareholders.length - 1]] = shareholderIndexes[shareholder] (contracts/external/DividendDistributor.sol#167-169) - addShareholder(shareholder) (contracts/external/DividendDistributor.sol#66) - shareholders.push(shareholder) (contracts/external/DividendDistributor.sol#144) - removeShareholder(shareholder) (contracts/external/DividendDistributor.sol#68) - shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length - 1] (contracts/external/DividendDistributor.sol#164-166) - shareholders.pop() (contracts/external/DividendDistributor.sol#170) - shares[shareholder].amount = amount (contracts/external/DividendDistributor.sol#72) - shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount) (contracts/external/DividendDistributor.sol#74-76) - totalShares = totalShares.sub(shares[shareholder].amount).add(amount) (contracts/external/DividendDistributor.sol#71) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4 DividendDistributor.currentIndex (contracts/external/DividendDistributor.sol#37) is never used in DividendDistributor (contracts/external/DividendDistributor.sol#9-172) Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable DividendDistributor.currentIndex (contracts/external/DividendDistributor.sol#37) should be constant DividendDistributor.dividendsPerShareAccuracyFactor (contracts/external/DividendDistributor.sol#32) should be constant Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant . analyzed (5 contracts with 100 detectors), 10 result(s) found
{
"solc": {
"status": "ok",
"use_rc": 0,
"version": "0.6.0",
"strategy": "solc-select",
"solc_path": "/var/www/tripwire/.venv/bin/solc",
"install_rc": 0,
"use_stderr": null,
"use_stdout": "Switched global version to 0.6.0",
"install_stderr": null,
"install_stdout": "Version '0.6.0' is already installed, skipping..."
},
"solc_args": "--base-path /tmp/slither-b4rpb__s --allow-paths /tmp/slither-b4rpb__s,/tmp/slither-b4rpb__s/lib,/tmp/slither-b4rpb__s/src",
"remappings": [],
"source_files": [
"contracts/external/DividendDistributor.sol",
"contracts/external/IDividendDistributor.sol",
"contracts/external/SafeMath.sol",
"contracts/external/IERC20.sol",
"contracts/external/ReentrancyGuard.sol"
],
"contract_count": 0,
"contract_names": [],
"detector_count": 10,
"workspace_hash": "7c91aa4004e9d78137f8c16c8afb3305a7797669099be172dedc488878213eed",
"duration_seconds": 0.48885154724121094,
"solc_version_requested": "0.6.12"
}
{"no_findings":false,"summary":"The first-party code is limited to a dividend distributor and related interfaces/libs. I found two low-severity denial-of-service/invariant issues in the distributor’s payout and deposit paths.","findings":[{"severity":"low","category":"other","title":"Reverting shareholder contracts can block share updates","exploit_scenario":"A holder can own shares through a contract account whose `receive`/fallback always reverts or needs more than 2300 gas. Once that holder has unpaid earnings, any later `setShare(holder, ...)` call first tries to pay them via `transfer()`. That payout revert bubbles up and aborts `setShare`, so any parent token flow that updates shares during transfers/sells can no longer modify that holder’s position.","recommendation":"Do not make share bookkeeping depend on a push-payment succeeding. Prefer a pull-based withdrawal model, or use a low-level call and record failed payouts so `setShare` can still complete.","evidence":"`setShare()` unconditionally calls `distributeDividend()` for existing holders before mutating balances. `distributeDividend()` then uses `shareholder.transfer(amount)`, which reverts for non-payable or gas-heavy recipients and therefore reverts the entire share update.","locations":["contracts/external/DividendDistributor.sol:61","contracts/external/DividendDistributor.sol:62","contracts/external/DividendDistributor.sol:95"]},{"severity":"low","category":"math","title":"Deposits revert when no shares exist","exploit_scenario":"If the parent token calls `deposit()` before any shareholder has been registered, or after all shareholders have been removed, the function divides by `totalShares == 0` and hard-reverts. In integrations that call the distributor during automated fee processing, that can temporarily DoS the upstream fee/swap path until a non-zero share exists again.","recommendation":"Guard `deposit()` with a `totalShares > 0` check and either reject upstream calls earlier or hold pending ETH until shares exist.","evidence":"`deposit()` computes `msg.value / totalShares` without validating that `totalShares` is non-zero. `totalShares` starts at zero and is adjusted directly by `setShare()`, including down to zero when the last holder is removed.","locations":["contracts/external/DividendDistributor.sol:79","contracts/external/DividendDistributor.sol:82","contracts/external/DividendDistributor.sol:71"]}]}
OpenAI Codex v0.118.0 (research preview)
--------
workdir: /tmp/codex-97wem3ip
model: gpt-5.4
provider: openai
approval: never
sandbox: read-only
reasoning effort: high
reasoning summaries: none
session id: 019d5683-0292-7233-b261-6afbb288fd5b
--------
user
You are a security auditor. Audit this Solidity codebase for exploitable vulnerabilities.
Focus on: reentrancy, access control, upgradeability/proxy issues, signature validation, oracle manipulation,
accounting/invariant breaks, external call patterns, unchecked return values, and dangerous delegatecall.
Scope rules:
- You MUST fully read `AUDIT_BUNDLE.txt` before concluding. It contains the complete contents of all first-party Solidity sources in this workspace.
- Treat `lib/` and `@openzeppelin/` as third-party dependencies; skip them unless there is a concrete misuse angle in first-party code.
- If there are only dependency files and no first-party sources, set no_findings=true and explain in summary.
Output MUST be valid JSON matching the provided schema.
- If you find nothing meaningful: set no_findings=true and findings=[].
- Otherwise: set no_findings=false and include findings with severity/category/title and file/line locations when possible.
Output constraints (IMPORTANT):
- severity MUST be exactly one of: info, low, medium, high, critical (lowercase).
- category MUST be exactly one of: access_control, reentrancy, math, oracle, upgradeability, auth, other.
Keep summary short and concrete.
warning: Codex could not find system bubblewrap on PATH. Please install bubblewrap with your package manager. Codex will use the vendored bubblewrap in the meantime.
exec
/bin/bash -lc pwd in /tmp/codex-97wem3ip
exec
/bin/bash -lc 'wc -l AUDIT_BUNDLE.txt' in /tmp/codex-97wem3ip
succeeded in 0ms:
/tmp/codex-97wem3ip
succeeded in 0ms:
484 AUDIT_BUNDLE.txt
exec
/bin/bash -lc 'ls -la' in /tmp/codex-97wem3ip
succeeded in 0ms:
total 56
drwx------ 3 noahkuhn noahkuhn 4096 Apr 4 03:21 .
drwxrwxrwt 252 nobody nogroup 24576 Apr 4 03:21 ..
-rw-rw-r-- 1 noahkuhn noahkuhn 14844 Apr 4 03:21 AUDIT_BUNDLE.txt
-rw-rw-r-- 1 noahkuhn noahkuhn 815 Apr 4 03:21 codex-output-schema.json
drwxrwxr-x 3 noahkuhn noahkuhn 4096 Apr 4 03:21 contracts
exec
/bin/bash -lc 'find contracts -maxdepth 3 -type f | sort' in /tmp/codex-97wem3ip
succeeded in 0ms:
contracts/external/DividendDistributor.sol
contracts/external/IDividendDistributor.sol
contracts/external/IERC20.sol
contracts/external/ReentrancyGuard.sol
contracts/external/SafeMath.sol
exec
/bin/bash -lc "sed -n '1,220p' AUDIT_BUNDLE.txt" in /tmp/codex-97wem3ip
succeeded in 0ms:
This file concatenates the full contents of first-party Solidity sources for auditing.
Do not treat dependency code under lib/ or @openzeppelin/ as first-party.
================================================================================
FILE: contracts/external/DividendDistributor.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import './IDividendDistributor.sol';
import './SafeMath.sol';
import './IERC20.sol';
import './ReentrancyGuard.sol';
contract DividendDistributor is IDividendDistributor, ReentrancyGuard {
using SafeMath for uint256;
event DividendDistributed(address shareholder, uint256 amount);
address _token;
struct Share {
uint256 amount;
uint256 totalExcluded;
uint256 totalRealised;
}
address[] shareholders;
mapping(address => uint256) shareholderIndexes;
mapping(address => uint256) shareholderClaims;
mapping(address => Share) public shares;
uint256 public totalShares;
uint256 public totalDividends;
uint256 public totalDistributed;
uint256 public dividendsPerShare;
uint256 public dividendsPerShareAccuracyFactor = 10**36;
uint256 public minPeriod = 1 hours;
uint256 public minDistribution = 1 * (10**18);
uint256 currentIndex;
modifier onlyToken() {
require(msg.sender == _token);
_;
}
constructor() public {
_token = msg.sender;
}
function setDistributionCriteria(
uint256 _minPeriod,
uint256 _minDistribution
) external override onlyToken {
minPeriod = _minPeriod;
minDistribution = _minDistribution;
}
function setShare(address shareholder, uint256 amount)
external
override
onlyToken
{
if (shares[shareholder].amount > 0) {
distributeDividend(payable(shareholder));
}
if (amount > 0 && shares[shareholder].amount == 0) {
addShareholder(shareholder);
} else if (amount == 0 && shares[shareholder].amount > 0) {
removeShareholder(shareholder);
}
totalShares = totalShares.sub(shares[shareholder].amount).add(amount);
shares[shareholder].amount = amount;
shares[shareholder].totalExcluded = getCumulativeDividends(
shares[shareholder].amount
);
}
function deposit() external payable override onlyToken {
totalDividends = totalDividends.add(msg.value);
dividendsPerShare = dividendsPerShare.add(
dividendsPerShareAccuracyFactor.mul(msg.value).div(totalShares)
);
}
function distributeDividend(address payable shareholder) internal nonReentrant {
if (shares[shareholder].amount == 0) {
return;
}
uint256 amount = getUnpaidEarnings(shareholder);
if (amount > 0) {
totalDistributed = totalDistributed.add(amount);
shareholder.transfer(amount);
shareholderClaims[shareholder] = block.timestamp;
shares[shareholder].totalRealised = shares[shareholder]
.totalRealised
.add(amount);
shares[shareholder].totalExcluded = getCumulativeDividends(
shares[shareholder].amount
);
emit DividendDistributed(shareholder, amount);
}
}
function claimDividend() external {
distributeDividend(msg.sender);
}
function getUnpaidEarnings(address shareholder)
public
view
returns (uint256)
{
if (shares[shareholder].amount == 0) {
return 0;
}
uint256 shareholderTotalDividends = getCumulativeDividends(
shares[shareholder].amount
);
uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded;
if (shareholderTotalDividends <= shareholderTotalExcluded) {
return 0;
}
return shareholderTotalDividends.sub(shareholderTotalExcluded);
}
function getCumulativeDividends(uint256 share)
internal
view
returns (uint256)
{
return
share.mul(dividendsPerShare).div(dividendsPerShareAccuracyFactor);
}
function addShareholder(address shareholder) internal {
shareholderIndexes[shareholder] = shareholders.length;
shareholders.push(shareholder);
}
function getShareholders()
external
view
returns (address[] memory)
{
return shareholders;
}
function getShareholderAmount(address shareholder)
external
view
returns (uint256)
{
return shares[shareholder].amount;
}
function removeShareholder(address shareholder) internal {
shareholders[shareholderIndexes[shareholder]] = shareholders[
shareholders.length - 1
];
shareholderIndexes[
shareholders[shareholders.length - 1]
] = shareholderIndexes[shareholder];
shareholders.pop();
}
}
================================================================================
FILE: contracts/external/IDividendDistributor.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
interface IDividendDistributor {
function setDistributionCriteria(
uint256 _minPeriod,
uint256 _minDistribution
) external;
function setShare(address shareholder, uint256 amount) external;
function deposit() external payable;
}
================================================================================
FILE: contracts/external/IERC20.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
exec
/bin/bash -lc "sed -n '221,484p' AUDIT_BUNDLE.txt" in /tmp/codex-97wem3ip
succeeded in 0ms:
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @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);
}
================================================================================
FILE: contracts/external/ReentrancyGuard.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() public {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, 'ReentrancyGuard: reentrant call');
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
modifier isHuman() {
require(tx.origin == msg.sender, 'sorry humans only');
_;
}
}
================================================================================
FILE: contracts/external/SafeMath.sol
================================================================================
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'SafeMath: addition overflow');
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, 'SafeMath: subtraction overflow');
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, 'SafeMath: multiplication overflow');
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, 'SafeMath: division by zero');
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, 'SafeMath: modulo by zero');
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
exec
/bin/bash -lc "nl -ba contracts/external/DividendDistributor.sol | sed -n '1,220p'" in /tmp/codex-97wem3ip
succeeded in 0ms:
1 // SPDX-License-Identifier: MIT
2 pragma solidity ^0.6.0;
3
4 import './IDividendDistributor.sol';
5 import './SafeMath.sol';
6 import './IERC20.sol';
7 import './ReentrancyGuard.sol';
8
9 contract DividendDistributor is IDividendDistributor, ReentrancyGuard {
10 using SafeMath for uint256;
11
12 event DividendDistributed(address shareholder, uint256 amount);
13
14 address _token;
15
16 struct Share {
17 uint256 amount;
18 uint256 totalExcluded;
19 uint256 totalRealised;
20 }
21
22 address[] shareholders;
23 mapping(address => uint256) shareholderIndexes;
24 mapping(address => uint256) shareholderClaims;
25
26 mapping(address => Share) public shares;
27
28 uint256 public totalShares;
29 uint256 public totalDividends;
30 uint256 public totalDistributed;
31 uint256 public dividendsPerShare;
32 uint256 public dividendsPerShareAccuracyFactor = 10**36;
33
34 uint256 public minPeriod = 1 hours;
35 uint256 public minDistribution = 1 * (10**18);
36
37 uint256 currentIndex;
38
39 modifier onlyToken() {
40 require(msg.sender == _token);
41 _;
42 }
43
44 constructor() public {
45 _token = msg.sender;
46 }
47
48 function setDistributionCriteria(
49 uint256 _minPeriod,
50 uint256 _minDistribution
51 ) external override onlyToken {
52 minPeriod = _minPeriod;
53 minDistribution = _minDistribution;
54 }
55
56 function setShare(address shareholder, uint256 amount)
57 external
58 override
59 onlyToken
60 {
61 if (shares[shareholder].amount > 0) {
62 distributeDividend(payable(shareholder));
63 }
64
65 if (amount > 0 && shares[shareholder].amount == 0) {
66 addShareholder(shareholder);
67 } else if (amount == 0 && shares[shareholder].amount > 0) {
68 removeShareholder(shareholder);
69 }
70
71 totalShares = totalShares.sub(shares[shareholder].amount).add(amount);
72 shares[shareholder].amount = amount;
73
74 shares[shareholder].totalExcluded = getCumulativeDividends(
75 shares[shareholder].amount
76 );
77 }
78
79 function deposit() external payable override onlyToken {
80 totalDividends = totalDividends.add(msg.value);
81 dividendsPerShare = dividendsPerShare.add(
82 dividendsPerShareAccuracyFactor.mul(msg.value).div(totalShares)
83 );
84 }
85
86 function distributeDividend(address payable shareholder) internal nonReentrant {
87 if (shares[shareholder].amount == 0) {
88 return;
89 }
90
91 uint256 amount = getUnpaidEarnings(shareholder);
92
93 if (amount > 0) {
94 totalDistributed = totalDistributed.add(amount);
95 shareholder.transfer(amount);
96 shareholderClaims[shareholder] = block.timestamp;
97 shares[shareholder].totalRealised = shares[shareholder]
98 .totalRealised
99 .add(amount);
100 shares[shareholder].totalExcluded = getCumulativeDividends(
101 shares[shareholder].amount
102 );
103
104 emit DividendDistributed(shareholder, amount);
105 }
106 }
107
108 function claimDividend() external {
109 distributeDividend(msg.sender);
110 }
111
112 function getUnpaidEarnings(address shareholder)
113 public
114 view
115 returns (uint256)
116 {
117 if (shares[shareholder].amount == 0) {
118 return 0;
119 }
120
121 uint256 shareholderTotalDividends = getCumulativeDividends(
122 shares[shareholder].amount
123 );
124 uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded;
125
126 if (shareholderTotalDividends <= shareholderTotalExcluded) {
127 return 0;
128 }
129
130 return shareholderTotalDividends.sub(shareholderTotalExcluded);
131 }
132
133 function getCumulativeDividends(uint256 share)
134 internal
135 view
136 returns (uint256)
137 {
138 return
139 share.mul(dividendsPerShare).div(dividendsPerShareAccuracyFactor);
140 }
141
142 function addShareholder(address shareholder) internal {
143 shareholderIndexes[shareholder] = shareholders.length;
144 shareholders.push(shareholder);
145 }
146
147 function getShareholders()
148 external
149 view
150 returns (address[] memory)
151 {
152 return shareholders;
153 }
154
155 function getShareholderAmount(address shareholder)
156 external
157 view
158 returns (uint256)
159 {
160 return shares[shareholder].amount;
161 }
162
163 function removeShareholder(address shareholder) internal {
164 shareholders[shareholderIndexes[shareholder]] = shareholders[
165 shareholders.length - 1
166 ];
167 shareholderIndexes[
168 shareholders[shareholders.length - 1]
169 ] = shareholderIndexes[shareholder];
170 shareholders.pop();
171 }
172 }
exec
/bin/bash -lc "nl -ba contracts/external/ReentrancyGuard.sol | sed -n '1,120p'" in /tmp/codex-97wem3ip
succeeded in 0ms:
1 // SPDX-License-Identifier: MIT
2 pragma solidity ^0.6.0;
3
4 abstract contract ReentrancyGuard {
5 uint256 private constant _NOT_ENTERED = 1;
6 uint256 private constant _ENTERED = 2;
7
8 uint256 private _status;
9
10 constructor() public {
11 _status = _NOT_ENTERED;
12 }
13
14 modifier nonReentrant() {
15 require(_status != _ENTERED, 'ReentrancyGuard: reentrant call');
16 _status = _ENTERED;
17 _;
18 _status = _NOT_ENTERED;
19 }
20
21 modifier isHuman() {
22 require(tx.origin == msg.sender, 'sorry humans only');
23 _;
24 }
25 }
exec
/bin/bash -lc true in /tmp/codex-97wem3ip
succeeded in 0ms:
exec
/bin/bash -lc "printf ''" in /tmp/codex-97wem3ip
succeeded in 0ms:
exec
/bin/bash -lc 'echo audit-in-progress >/dev/null' in /tmp/codex-97wem3ip
succeeded in 0ms:
I’ve read the full audit bundle and I’m now validating whether the dividend distributor has concrete exploit paths versus edge-case-only bugs. Next I’m tightening line references and severity so the final report stays limited to actionable issues.
✓ Read AUDIT_BUNDLE.txt completely and enumerate first-party contracts
→ Validate concrete exploit scenarios and collect line references
• Emit final JSON report
codex
{"no_findings":false,"summary":"The first-party code is limited to a dividend distributor and related interfaces/libs. I found two low-severity denial-of-service/invariant issues in the distributor’s payout and deposit paths.","findings":[{"severity":"low","category":"other","title":"Reverting shareholder contracts can block share updates","exploit_scenario":"A holder can own shares through a contract account whose `receive`/fallback always reverts or needs more than 2300 gas. Once that holder has unpaid earnings, any later `setShare(holder, ...)` call first tries to pay them via `transfer()`. That payout revert bubbles up and aborts `setShare`, so any parent token flow that updates shares during transfers/sells can no longer modify that holder’s position.","recommendation":"Do not make share bookkeeping depend on a push-payment succeeding. Prefer a pull-based withdrawal model, or use a low-level call and record failed payouts so `setShare` can still complete.","evidence":"`setShare()` unconditionally calls `distributeDividend()` for existing holders before mutating balances. `distributeDividend()` then uses `shareholder.transfer(amount)`, which reverts for non-payable or gas-heavy recipients and therefore reverts the entire share update.","locations":["contracts/external/DividendDistributor.sol:61","contracts/external/DividendDistributor.sol:62","contracts/external/DividendDistributor.sol:95"]},{"severity":"low","category":"math","title":"Deposits revert when no shares exist","exploit_scenario":"If the parent token calls `deposit()` before any shareholder has been registered, or after all shareholders have been removed, the function divides by `totalShares == 0` and hard-reverts. In integrations that call the distributor during automated fee processing, that can temporarily DoS the upstream fee/swap path until a non-zero share exists again.","recommendation":"Guard `deposit()` with a `totalShares > 0` check and either reject upstream calls earlier or hold pending ETH until shares exist.","evidence":"`deposit()` computes `msg.value / totalShares` without validating that `totalShares` is non-zero. `totalShares` starts at zero and is adjusted directly by `setShare()`, including down to zero when the last holder is removed.","locations":["contracts/external/DividendDistributor.sol:79","contracts/external/DividendDistributor.sol:82","contracts/external/DividendDistributor.sol:71"]}]}
tokens used
35,199
{
"codex": {
"ran_at": "2026-04-04T03:23:37.793464+00:00",
"returncode": 0
},
"project": {
"mode": "source",
"file_count": 5,
"import_count": 4,
"first_party_contracts_count": 5
},
"summary": "The first-party code is limited to a dividend distributor and related interfaces/libs. I found two low-severity denial-of-service/invariant issues in the distributor\u2019s payout and deposit paths.",
"raw_final": {
"summary": "The first-party code is limited to a dividend distributor and related interfaces/libs. I found two low-severity denial-of-service/invariant issues in the distributor\u2019s payout and deposit paths.",
"findings": [
{
"title": "Reverting shareholder contracts can block share updates",
"category": "other",
"evidence": "`setShare()` unconditionally calls `distributeDividend()` for existing holders before mutating balances. `distributeDividend()` then uses `shareholder.transfer(amount)`, which reverts for non-payable or gas-heavy recipients and therefore reverts the entire share update.",
"severity": "low",
"locations": [
"contracts/external/DividendDistributor.sol:61",
"contracts/external/DividendDistributor.sol:62",
"contracts/external/DividendDistributor.sol:95"
],
"recommendation": "Do not make share bookkeeping depend on a push-payment succeeding. Prefer a pull-based withdrawal model, or use a low-level call and record failed payouts so `setShare` can still complete.",
"exploit_scenario": "A holder can own shares through a contract account whose `receive`/fallback always reverts or needs more than 2300 gas. Once that holder has unpaid earnings, any later `setShare(holder, ...)` call first tries to pay them via `transfer()`. That payout revert bubbles up and aborts `setShare`, so any parent token flow that updates shares during transfers/sells can no longer modify that holder\u2019s position."
},
{
"title": "Deposits revert when no shares exist",
"category": "math",
"evidence": "`deposit()` computes `msg.value / totalShares` without validating that `totalShares` is non-zero. `totalShares` starts at zero and is adjusted directly by `setShare()`, including down to zero when the last holder is removed.",
"severity": "low",
"locations": [
"contracts/external/DividendDistributor.sol:79",
"contracts/external/DividendDistributor.sol:82",
"contracts/external/DividendDistributor.sol:71"
],
"recommendation": "Guard `deposit()` with a `totalShares > 0` check and either reject upstream calls earlier or hold pending ETH until shares exist.",
"exploit_scenario": "If the parent token calls `deposit()` before any shareholder has been registered, or after all shareholders have been removed, the function divides by `totalShares == 0` and hard-reverts. In integrations that call the distributor during automated fee processing, that can temporarily DoS the upstream fee/swap path until a non-zero share exists again."
}
],
"no_findings": false
},
"no_findings": false,
"schema_version": 1
}
00000000: PUSH1 0x80 00000002: PUSH1 0x40 00000004: MSTORE 00000005: PUSH1 0x04 00000007: CALLDATASIZE 00000008: LT 00000009: PUSH2 0x00e8 0000000c: JUMPI 0000000d: PUSH1 0x00 0000000f: CALLDATALOAD 00000010: PUSH1 0xe0 00000012: SHR 00000013: DUP1 00000014: PUSH4 0x997664d7 00000019: GT 0000001a: PUSH2 0x008a 0000001d: JUMPI 0000001e: DUP1 0000001f: PUSH4 0xe2d2e219 00000024: GT 00000025: PUSH2 0x0059 00000028: JUMPI 00000029: DUP1 0000002a: PUSH4 0xe2d2e219 0000002f: EQ 00000030: PUSH2 0x02e2 00000033: JUMPI 00000034: DUP1 00000035: PUSH4 0xefca2eed 0000003a: EQ 0000003b: PUSH2 0x02f7 0000003e: JUMPI 0000003f: DUP1 00000040: PUSH4 0xf0fc6bca 00000045: EQ 00000046: PUSH2 0x030c 00000049: JUMPI 0000004a: DUP1 0000004b: PUSH4 0xffd49c84 00000050: EQ 00000051: PUSH2 0x0321 00000054: JUMPI 00000055: PUSH2 0x00e8 00000058: JUMP 00000059: JUMPDEST 0000005a: DUP1 0000005b: PUSH4 0x997664d7 00000060: EQ 00000061: PUSH2 0x0241 00000064: JUMPI 00000065: DUP1 00000066: PUSH4 0xabd37753 0000006b: EQ 0000006c: PUSH2 0x0256 0000006f: JUMPI 00000070: DUP1 00000071: PUSH4 0xce7c2ac2 00000076: EQ 00000077: PUSH2 0x0289 0000007a: JUMPI 0000007b: DUP1 0000007c: PUSH4 0xd0e30db0 00000081: EQ 00000082: PUSH2 0x02da 00000085: JUMPI 00000086: PUSH2 0x00e8 00000089: JUMP 0000008a: JUMPDEST 0000008b: DUP1 0000008c: PUSH4 0x2d48e896 00000091: GT 00000092: PUSH2 0x00c6 00000095: JUMPI 00000096: DUP1 00000097: PUSH4 0x2d48e896 0000009c: EQ 0000009d: PUSH2 0x0182 000000a0: JUMPI 000000a1: DUP1 000000a2: PUSH4 0x3a98ef39 000000a7: EQ 000000a8: PUSH2 0x01b2 000000ab: JUMPI 000000ac: DUP1 000000ad: PUSH4 0x41ca641e 000000b2: EQ 000000b3: PUSH2 0x01c7 000000b6: JUMPI 000000b7: DUP1 000000b8: PUSH4 0x4fab0ae8 000000bd: EQ 000000be: PUSH2 0x022c 000000c1: JUMPI 000000c2: PUSH2 0x00e8 000000c5: JUMP 000000c6: JUMPDEST 000000c7: DUP1 000000c8: PUSH4 0x11ce023d 000000cd: EQ 000000ce: PUSH2 0x00ed 000000d1: JUMPI 000000d2: DUP1 000000d3: PUSH4 0x14b6ca96 000000d8: EQ 000000d9: PUSH2 0x0114 000000dc: JUMPI 000000dd: DUP1 000000de: PUSH4 0x28fd3198 000000e3: EQ 000000e4: PUSH2 0x014f 000000e7: JUMPI 000000e8: JUMPDEST 000000e9: PUSH1 0x00 000000eb: DUP1 000000ec: REVERT 000000ed: JUMPDEST 000000ee: CALLVALUE 000000ef: DUP1 000000f0: ISZERO 000000f1: PUSH2 0x00f9 000000f4: JUMPI 000000f5: PUSH1 0x00 000000f7: DUP1 000000f8: REVERT 000000f9: JUMPDEST 000000fa: POP 000000fb: PUSH2 0x0102 000000fe: PUSH2 0x0336 00000101: JUMP 00000102: JUMPDEST 00000103: PUSH1 0x40 00000105: DUP1 00000106: MLOAD 00000107: SWAP2 00000108: DUP3 00000109: MSTORE 0000010a: MLOAD 0000010b: SWAP1 0000010c: DUP2 0000010d: SWAP1 0000010e: SUB 0000010f: PUSH1 0x20 00000111: ADD 00000112: SWAP1 00000113: RETURN 00000114: JUMPDEST 00000115: CALLVALUE 00000116: DUP1 00000117: ISZERO 00000118: PUSH2 0x0120 0000011b: JUMPI 0000011c: PUSH1 0x00 0000011e: DUP1 0000011f: REVERT 00000120: JUMPDEST 00000121: POP 00000122: PUSH2 0x014d 00000125: PUSH1 0x04 00000127: DUP1 00000128: CALLDATASIZE 00000129: SUB 0000012a: PUSH1 0x40 0000012c: DUP2 0000012d: LT 0000012e: ISZERO 0000012f: PUSH2 0x0137 00000132: JUMPI 00000133: PUSH1 0x00 00000135: DUP1 00000136: REVERT 00000137: JUMPDEST 00000138: POP 00000139: PUSH1 0x01 0000013b: PUSH1 0x01 0000013d: PUSH1 0xa0 0000013f: SHL 00000140: SUB 00000141: DUP2 00000142: CALLDATALOAD 00000143: AND 00000144: SWAP1 00000145: PUSH1 0x20 00000147: ADD 00000148: CALLDATALOAD 00000149: PUSH2 0x033c 0000014c: JUMP 0000014d: JUMPDEST 0000014e: STOP 0000014f: JUMPDEST 00000150: CALLVALUE 00000151: DUP1 00000152: ISZERO 00000153: PUSH2 0x015b 00000156: JUMPI 00000157: PUSH1 0x00 00000159: DUP1 0000015a: REVERT 0000015b: JUMPDEST 0000015c: POP 0000015d: PUSH2 0x0102 00000160: PUSH1 0x04 00000162: DUP1 00000163: CALLDATASIZE 00000164: SUB 00000165: PUSH1 0x20 00000167: DUP2 00000168: LT 00000169: ISZERO 0000016a: PUSH2 0x0172 0000016d: JUMPI 0000016e: PUSH1 0x00 00000170: DUP1 00000171: REVERT 00000172: JUMPDEST 00000173: POP 00000174: CALLDATALOAD 00000175: PUSH1 0x01 00000177: PUSH1 0x01 00000179: PUSH1 0xa0 0000017b: SHL 0000017c: SUB 0000017d: AND 0000017e: PUSH2 0x0461 00000181: JUMP 00000182: JUMPDEST 00000183: CALLVALUE 00000184: DUP1 00000185: ISZERO 00000186: PUSH2 0x018e 00000189: JUMPI 0000018a: PUSH1 0x00 0000018c: DUP1 0000018d: REVERT 0000018e: JUMPDEST 0000018f: POP 00000190: PUSH2 0x014d 00000193: PUSH1 0x04 00000195: DUP1 00000196: CALLDATASIZE 00000197: SUB 00000198: PUSH1 0x40 0000019a: DUP2 0000019b: LT 0000019c: ISZERO 0000019d: PUSH2 0x01a5 000001a0: JUMPI 000001a1: PUSH1 0x00 000001a3: DUP1 000001a4: REVERT 000001a5: JUMPDEST 000001a6: POP 000001a7: DUP1 000001a8: CALLDATALOAD 000001a9: SWAP1 000001aa: PUSH1 0x20 000001ac: ADD 000001ad: CALLDATALOAD 000001ae: PUSH2 0x04ed 000001b1: JUMP 000001b2: JUMPDEST 000001b3: CALLVALUE 000001b4: DUP1 000001b5: ISZERO 000001b6: PUSH2 0x01be 000001b9: JUMPI 000001ba: PUSH1 0x00 000001bc: DUP1 000001bd: REVERT 000001be: JUMPDEST 000001bf: POP 000001c0: PUSH2 0x0102 000001c3: PUSH2 0x050f 000001c6: JUMP 000001c7: JUMPDEST 000001c8: CALLVALUE 000001c9: DUP1 000001ca: ISZERO 000001cb: PUSH2 0x01d3 000001ce: JUMPI 000001cf: PUSH1 0x00 000001d1: DUP1 000001d2: REVERT 000001d3: JUMPDEST 000001d4: POP 000001d5: PUSH2 0x01dc 000001d8: PUSH2 0x0515 000001db: JUMP 000001dc: JUMPDEST 000001dd: PUSH1 0x40 000001df: DUP1 000001e0: MLOAD 000001e1: PUSH1 0x20 000001e3: DUP1 000001e4: DUP3 000001e5: MSTORE 000001e6: DUP4 000001e7: MLOAD 000001e8: DUP2 000001e9: DUP4 000001ea: ADD 000001eb: MSTORE 000001ec: DUP4 000001ed: MLOAD 000001ee: SWAP2 000001ef: SWAP3 000001f0: DUP4 000001f1: SWAP3 000001f2: SWAP1 000001f3: DUP4 000001f4: ADD 000001f5: SWAP2 000001f6: DUP6 000001f7: DUP2 000001f8: ADD 000001f9: SWAP2 000001fa: MUL 000001fb: DUP1 000001fc: DUP4 000001fd: DUP4 000001fe: PUSH1 0x00 00000200: JUMPDEST 00000201: DUP4 00000202: DUP2 00000203: LT 00000204: ISZERO 00000205: PUSH2 0x0218 00000208: JUMPI 00000209: DUP2 0000020a: DUP2 0000020b: ADD 0000020c: MLOAD 0000020d: DUP4 0000020e: DUP3 0000020f: ADD 00000210: MSTORE 00000211: PUSH1 0x20 00000213: ADD 00000214: PUSH2 0x0200 00000217: JUMP 00000218: JUMPDEST 00000219: POP 0000021a: POP 0000021b: POP 0000021c: POP 0000021d: SWAP1 0000021e: POP 0000021f: ADD 00000220: SWAP3 00000221: POP 00000222: POP 00000223: POP 00000224: PUSH1 0x40 00000226: MLOAD 00000227: DUP1 00000228: SWAP2 00000229: SUB 0000022a: SWAP1 0000022b: RETURN 0000022c: JUMPDEST 0000022d: CALLVALUE 0000022e: DUP1 0000022f: ISZERO 00000230: PUSH2 0x0238 00000233: JUMPI 00000234: PUSH1 0x00 00000236: DUP1 00000237: REVERT 00000238: JUMPDEST 00000239: POP 0000023a: PUSH2 0x0102 0000023d: PUSH2 0x0577 00000240: JUMP 00000241: JUMPDEST 00000242: CALLVALUE 00000243: DUP1 00000244: ISZERO 00000245: PUSH2 0x024d 00000248: JUMPI 00000249: PUSH1 0x00 0000024b: DUP1 0000024c: REVERT 0000024d: JUMPDEST 0000024e: POP 0000024f: PUSH2 0x0102 00000252: PUSH2 0x057d 00000255: JUMP 00000256: JUMPDEST 00000257: CALLVALUE 00000258: DUP1 00000259: ISZERO 0000025a: PUSH2 0x0262 0000025d: JUMPI 0000025e: PUSH1 0x00 00000260: DUP1 00000261: REVERT 00000262: JUMPDEST 00000263: POP 00000264: PUSH2 0x0102 00000267: PUSH1 0x04 00000269: DUP1 0000026a: CALLDATASIZE 0000026b: SUB 0000026c: PUSH1 0x20 0000026e: DUP2 0000026f: LT 00000270: ISZERO 00000271: PUSH2 0x0279 00000274: JUMPI 00000275: PUSH1 0x00 00000277: DUP1 00000278: REVERT 00000279: JUMPDEST 0000027a: POP 0000027b: CALLDATALOAD 0000027c: PUSH1 0x01 0000027e: PUSH1 0x01 00000280: PUSH1 0xa0 00000282: SHL 00000283: SUB 00000284: AND 00000285: PUSH2 0x0583 00000288: JUMP 00000289: JUMPDEST 0000028a: CALLVALUE 0000028b: DUP1 0000028c: ISZERO 0000028d: PUSH2 0x0295 00000290: JUMPI 00000291: PUSH1 0x00 00000293: DUP1 00000294: REVERT 00000295: JUMPDEST 00000296: POP 00000297: PUSH2 0x02bc 0000029a: PUSH1 0x04 0000029c: DUP1 0000029d: CALLDATASIZE 0000029e: SUB 0000029f: PUSH1 0x20 000002a1: DUP2 000002a2: LT 000002a3: ISZERO 000002a4: PUSH2 0x02ac 000002a7: JUMPI 000002a8: PUSH1 0x00 000002aa: DUP1 000002ab: REVERT 000002ac: JUMPDEST 000002ad: POP 000002ae: CALLDATALOAD 000002af: PUSH1 0x01 000002b1: PUSH1 0x01 000002b3: PUSH1 0xa0 000002b5: SHL 000002b6: SUB 000002b7: AND 000002b8: PUSH2 0x059e 000002bb: JUMP 000002bc: JUMPDEST 000002bd: PUSH1 0x40 000002bf: DUP1 000002c0: MLOAD 000002c1: SWAP4 000002c2: DUP5 000002c3: MSTORE 000002c4: PUSH1 0x20 000002c6: DUP5 000002c7: ADD 000002c8: SWAP3 000002c9: SWAP1 000002ca: SWAP3 000002cb: MSTORE 000002cc: DUP3 000002cd: DUP3 000002ce: ADD 000002cf: MSTORE 000002d0: MLOAD 000002d1: SWAP1 000002d2: DUP2 000002d3: SWAP1 000002d4: SUB 000002d5: PUSH1 0x60 000002d7: ADD 000002d8: SWAP1 000002d9: RETURN 000002da: JUMPDEST 000002db: PUSH2 0x014d 000002de: PUSH2 0x05bf 000002e1: JUMP 000002e2: JUMPDEST 000002e3: CALLVALUE 000002e4: DUP1 000002e5: ISZERO 000002e6: PUSH2 0x02ee 000002e9: JUMPI 000002ea: PUSH1 0x00 000002ec: DUP1 000002ed: REVERT 000002ee: JUMPDEST 000002ef: POP 000002f0: PUSH2 0x0102 000002f3: PUSH2 0x0612 000002f6: JUMP 000002f7: JUMPDEST 000002f8: CALLVALUE 000002f9: DUP1 000002fa: ISZERO 000002fb: PUSH2 0x0303 000002fe: JUMPI 000002ff: PUSH1 0x00 00000301: DUP1 00000302: REVERT 00000303: JUMPDEST 00000304: POP 00000305: PUSH2 0x0102 00000308: PUSH2 0x0618 0000030b: JUMP 0000030c: JUMPDEST 0000030d: CALLVALUE 0000030e: DUP1 0000030f: ISZERO 00000310: PUSH2 0x0318 00000313: JUMPI 00000314: PUSH1 0x00 00000316: DUP1 00000317: REVERT 00000318: JUMPDEST 00000319: POP 0000031a: PUSH2 0x014d 0000031d: PUSH2 0x061e 00000320: JUMP 00000321: JUMPDEST 00000322: CALLVALUE 00000323: DUP1 00000324: ISZERO 00000325: PUSH2 0x032d 00000328: JUMPI 00000329: PUSH1 0x00 0000032b: DUP1 0000032c: REVERT 0000032d: JUMPDEST 0000032e: POP 0000032f: PUSH2 0x0102 00000332: PUSH2 0x0629 00000335: JUMP 00000336: JUMPDEST 00000337: PUSH1 0x0a 00000339: SLOAD 0000033a: DUP2 0000033b: JUMP 0000033c: JUMPDEST 0000033d: PUSH1 0x01 0000033f: SLOAD 00000340: PUSH1 0x01 00000342: PUSH1 0x01 00000344: PUSH1 0xa0 00000346: SHL 00000347: SUB 00000348: AND 00000349: CALLER 0000034a: EQ 0000034b: PUSH2 0x0353 0000034e: JUMPI 0000034f: PUSH1 0x00 00000351: DUP1 00000352: REVERT 00000353: JUMPDEST 00000354: PUSH1 0x01 00000356: PUSH1 0x01 00000358: PUSH1 0xa0 0000035a: SHL 0000035b: SUB 0000035c: DUP3 0000035d: AND 0000035e: PUSH1 0x00 00000360: SWAP1 00000361: DUP2 00000362: MSTORE 00000363: PUSH1 0x05 00000365: PUSH1 0x20 00000367: MSTORE 00000368: PUSH1 0x40 0000036a: SWAP1 0000036b: KECCAK256 0000036c: SLOAD 0000036d: ISZERO 0000036e: PUSH2 0x037a 00000371: JUMPI 00000372: PUSH2 0x037a 00000375: DUP3 00000376: PUSH2 0x062f 00000379: JUMP 0000037a: JUMPDEST 0000037b: PUSH1 0x00 0000037d: DUP2 0000037e: GT 0000037f: DUP1 00000380: ISZERO 00000381: PUSH2 0x03a0 00000384: JUMPI 00000385: POP 00000386: PUSH1 0x01 00000388: PUSH1 0x01 0000038a: PUSH1 0xa0 0000038c: SHL 0000038d: SUB 0000038e: DUP3 0000038f: AND 00000390: PUSH1 0x00 00000392: SWAP1 00000393: DUP2 00000394: MSTORE 00000395: PUSH1 0x05 00000397: PUSH1 0x20 00000399: MSTORE 0000039a: PUSH1 0x40 0000039c: SWAP1 0000039d: KECCAK256 0000039e: SLOAD 0000039f: ISZERO 000003a0: JUMPDEST 000003a1: ISZERO 000003a2: PUSH2 0x03b3 000003a5: JUMPI 000003a6: PUSH2 0x03ae 000003a9: DUP3 000003aa: PUSH2 0x07ca 000003ad: JUMP 000003ae: JUMPDEST 000003af: PUSH2 0x03e6 000003b2: JUMP 000003b3: JUMPDEST 000003b4: DUP1 000003b5: ISZERO 000003b6: DUP1 000003b7: ISZERO 000003b8: PUSH2 0x03d8 000003bb: JUMPI 000003bc: POP 000003bd: PUSH1 0x01 000003bf: PUSH1 0x01 000003c1: PUSH1 0xa0 000003c3: SHL 000003c4: SUB 000003c5: DUP3 000003c6: AND 000003c7: PUSH1 0x00 000003c9: SWAP1 000003ca: DUP2 000003cb: MSTORE 000003cc: PUSH1 0x05 000003ce: PUSH1 0x20 000003d0: MSTORE 000003d1: PUSH1 0x40 000003d3: SWAP1 000003d4: KECCAK256 000003d5: SLOAD 000003d6: ISZERO 000003d7: ISZERO 000003d8: JUMPDEST 000003d9: ISZERO 000003da: PUSH2 0x03e6 000003dd: JUMPI 000003de: PUSH2 0x03e6 000003e1: DUP3 000003e2: PUSH2 0x082b 000003e5: JUMP 000003e6: JUMPDEST 000003e7: PUSH1 0x01 000003e9: PUSH1 0x01 000003eb: PUSH1 0xa0 000003ed: SHL 000003ee: SUB 000003ef: DUP3 000003f0: AND 000003f1: PUSH1 0x00 000003f3: SWAP1 000003f4: DUP2 000003f5: MSTORE 000003f6: PUSH1 0x05 000003f8: PUSH1 0x20 000003fa: MSTORE 000003fb: PUSH1 0x40 000003fd: SWAP1 000003fe: KECCAK256 000003ff: SLOAD 00000400: PUSH1 0x06 00000402: SLOAD 00000403: PUSH2 0x0417 00000406: SWAP2 00000407: DUP4 00000408: SWAP2 00000409: PUSH2 0x0411 0000040c: SWAP2 0000040d: PUSH2 0x0918 00000410: JUMP 00000411: JUMPDEST 00000412: SWAP1 00000413: PUSH2 0x0963 00000416: JUMP 00000417: JUMPDEST 00000418: PUSH1 0x06 0000041a: SSTORE 0000041b: PUSH1 0x01 0000041d: PUSH1 0x01 0000041f: PUSH1 0xa0 00000421: SHL 00000422: SUB 00000423: DUP3 00000424: AND 00000425: PUSH1 0x00 00000427: SWAP1 00000428: DUP2 00000429: MSTORE 0000042a: PUSH1 0x05 0000042c: PUSH1 0x20 0000042e: MSTORE 0000042f: PUSH1 0x40 00000431: SWAP1 00000432: KECCAK256 00000433: DUP2 00000434: SWAP1 00000435: SSTORE 00000436: PUSH2 0x043e 00000439: DUP2 0000043a: PUSH2 0x09bd 0000043d: JUMP 0000043e: JUMPDEST 0000043f: PUSH1 0x01 00000441: PUSH1 0x01 00000443: PUSH1 0xa0 00000445: SHL 00000446: SUB 00000447: SWAP1 00000448: SWAP3 00000449: AND 0000044a: PUSH1 0x00 0000044c: SWAP1 0000044d: DUP2 0000044e: MSTORE 0000044f: PUSH1 0x05 00000451: PUSH1 0x20 00000453: MSTORE 00000454: PUSH1 0x40 00000456: SWAP1 00000457: KECCAK256 00000458: PUSH1 0x01 0000045a: ADD 0000045b: SWAP2 0000045c: SWAP1 0000045d: SWAP2 0000045e: SSTORE 0000045f: POP 00000460: JUMP 00000461: JUMPDEST 00000462: PUSH1 0x01 00000464: PUSH1 0x01 00000466: PUSH1 0xa0 00000468: SHL 00000469: SUB 0000046a: DUP2 0000046b: AND 0000046c: PUSH1 0x00 0000046e: SWAP1 0000046f: DUP2 00000470: MSTORE 00000471: PUSH1 0x05 00000473: PUSH1 0x20 00000475: MSTORE 00000476: PUSH1 0x40 00000478: DUP2 00000479: KECCAK256 0000047a: SLOAD 0000047b: PUSH2 0x0486 0000047e: JUMPI 0000047f: POP 00000480: PUSH1 0x00 00000482: PUSH2 0x04e8 00000485: JUMP 00000486: JUMPDEST 00000487: PUSH1 0x01 00000489: PUSH1 0x01 0000048b: PUSH1 0xa0 0000048d: SHL 0000048e: SUB 0000048f: DUP3 00000490: AND 00000491: PUSH1 0x00 00000493: SWAP1 00000494: DUP2 00000495: MSTORE 00000496: PUSH1 0x05 00000498: PUSH1 0x20 0000049a: MSTORE 0000049b: PUSH1 0x40 0000049d: DUP2 0000049e: KECCAK256 0000049f: SLOAD 000004a0: PUSH2 0x04a8 000004a3: SWAP1 000004a4: PUSH2 0x09bd 000004a7: JUMP 000004a8: JUMPDEST 000004a9: PUSH1 0x01 000004ab: PUSH1 0x01 000004ad: PUSH1 0xa0 000004af: SHL 000004b0: SUB 000004b1: DUP5 000004b2: AND 000004b3: PUSH1 0x00 000004b5: SWAP1 000004b6: DUP2 000004b7: MSTORE 000004b8: PUSH1 0x05 000004ba: PUSH1 0x20 000004bc: MSTORE 000004bd: PUSH1 0x40 000004bf: SWAP1 000004c0: KECCAK256 000004c1: PUSH1 0x01 000004c3: ADD 000004c4: SLOAD 000004c5: SWAP1 000004c6: SWAP2 000004c7: POP 000004c8: DUP1 000004c9: DUP3 000004ca: GT 000004cb: PUSH2 0x04d9 000004ce: JUMPI 000004cf: PUSH1 0x00 000004d1: SWAP3 000004d2: POP 000004d3: POP 000004d4: POP 000004d5: PUSH2 0x04e8 000004d8: JUMP 000004d9: JUMPDEST 000004da: PUSH2 0x04e3 000004dd: DUP3 000004de: DUP3 000004df: PUSH2 0x0918 000004e2: JUMP 000004e3: JUMPDEST 000004e4: SWAP3 000004e5: POP 000004e6: POP 000004e7: POP 000004e8: JUMPDEST 000004e9: SWAP2 000004ea: SWAP1 000004eb: POP 000004ec: JUMP 000004ed: JUMPDEST 000004ee: PUSH1 0x01 000004f0: SLOAD 000004f1: PUSH1 0x01 000004f3: PUSH1 0x01 000004f5: PUSH1 0xa0 000004f7: SHL 000004f8: SUB 000004f9: AND 000004fa: CALLER 000004fb: EQ 000004fc: PUSH2 0x0504 000004ff: JUMPI 00000500: PUSH1 0x00 00000502: DUP1 00000503: REVERT 00000504: JUMPDEST 00000505: PUSH1 0x0b 00000507: SWAP2 00000508: SWAP1 00000509: SWAP2 0000050a: SSTORE 0000050b: PUSH1 0x0c 0000050d: SSTORE 0000050e: JUMP 0000050f: JUMPDEST 00000510: PUSH1 0x06 00000512: SLOAD 00000513: DUP2 00000514: JUMP 00000515: JUMPDEST 00000516: PUSH1 0x60 00000518: PUSH1 0x02 0000051a: DUP1 0000051b: SLOAD 0000051c: DUP1 0000051d: PUSH1 0x20 0000051f: MUL 00000520: PUSH1 0x20 00000522: ADD 00000523: PUSH1 0x40 00000525: MLOAD 00000526: SWAP1 00000527: DUP2 00000528: ADD 00000529: PUSH1 0x40 0000052b: MSTORE 0000052c: DUP1 0000052d: SWAP3 0000052e: SWAP2 0000052f: SWAP1 00000530: DUP2 00000531: DUP2 00000532: MSTORE 00000533: PUSH1 0x20 00000535: ADD 00000536: DUP3 00000537: DUP1 00000538: SLOAD 00000539: DUP1 0000053a: ISZERO 0000053b: PUSH2 0x056d 0000053e: JUMPI 0000053f: PUSH1 0x20 00000541: MUL 00000542: DUP3 00000543: ADD 00000544: SWAP2 00000545: SWAP1 00000546: PUSH1 0x00 00000548: MSTORE 00000549: PUSH1 0x20 0000054b: PUSH1 0x00 0000054d: KECCAK256 0000054e: SWAP1 0000054f: JUMPDEST 00000550: DUP2 00000551: SLOAD 00000552: PUSH1 0x01 00000554: PUSH1 0x01 00000556: PUSH1 0xa0 00000558: SHL 00000559: SUB 0000055a: AND 0000055b: DUP2 0000055c: MSTORE 0000055d: PUSH1 0x01 0000055f: SWAP1 00000560: SWAP2 00000561: ADD 00000562: SWAP1 00000563: PUSH1 0x20 00000565: ADD 00000566: DUP1 00000567: DUP4 00000568: GT 00000569: PUSH2 0x054f 0000056c: JUMPI 0000056d: JUMPDEST 0000056e: POP 0000056f: POP 00000570: POP 00000571: POP 00000572: POP 00000573: SWAP1 00000574: POP 00000575: SWAP1 00000576: JUMP 00000577: JUMPDEST 00000578: PUSH1 0x0c 0000057a: SLOAD 0000057b: DUP2 0000057c: JUMP 0000057d: JUMPDEST 0000057e: PUSH1 0x07 00000580: SLOAD 00000581: DUP2 00000582: JUMP 00000583: JUMPDEST 00000584: PUSH1 0x01 00000586: PUSH1 0x01 00000588: PUSH1 0xa0 0000058a: SHL 0000058b: SUB 0000058c: AND 0000058d: PUSH1 0x00 0000058f: SWAP1 00000590: DUP2 00000591: MSTORE 00000592: PUSH1 0x05 00000594: PUSH1 0x20 00000596: MSTORE 00000597: PUSH1 0x40 00000599: SWAP1 0000059a: KECCAK256 0000059b: SLOAD 0000059c: SWAP1 0000059d: JUMP 0000059e: JUMPDEST 0000059f: PUSH1 0x05 000005a1: PUSH1 0x20 000005a3: MSTORE 000005a4: PUSH1 0x00 000005a6: SWAP1 000005a7: DUP2 000005a8: MSTORE 000005a9: PUSH1 0x40 000005ab: SWAP1 000005ac: KECCAK256 000005ad: DUP1 000005ae: SLOAD 000005af: PUSH1 0x01 000005b1: DUP3 000005b2: ADD 000005b3: SLOAD 000005b4: PUSH1 0x02 000005b6: SWAP1 000005b7: SWAP3 000005b8: ADD 000005b9: SLOAD 000005ba: SWAP1 000005bb: SWAP2 000005bc: SWAP1 000005bd: DUP4 000005be: JUMP 000005bf: JUMPDEST 000005c0: PUSH1 0x01 000005c2: SLOAD 000005c3: PUSH1 0x01 000005c5: PUSH1 0x01 000005c7: PUSH1 0xa0 000005c9: SHL 000005ca: SUB 000005cb: AND 000005cc: CALLER 000005cd: EQ 000005ce: PUSH2 0x05d6 000005d1: JUMPI 000005d2: PUSH1 0x00 000005d4: DUP1 000005d5: REVERT 000005d6: JUMPDEST 000005d7: PUSH1 0x07 000005d9: SLOAD 000005da: PUSH2 0x05e3 000005dd: SWAP1 000005de: CALLVALUE 000005df: PUSH2 0x0963 000005e2: JUMP 000005e3: JUMPDEST 000005e4: PUSH1 0x07 000005e6: SSTORE 000005e7: PUSH1 0x06 000005e9: SLOAD 000005ea: PUSH1 0x0a 000005ec: SLOAD 000005ed: PUSH2 0x060d 000005f0: SWAP2 000005f1: PUSH2 0x0604 000005f4: SWAP2 000005f5: PUSH2 0x05fe 000005f8: SWAP1 000005f9: CALLVALUE 000005fa: PUSH2 0x09da 000005fd: JUMP 000005fe: JUMPDEST 000005ff: SWAP1 00000600: PUSH2 0x0a33 00000603: JUMP 00000604: JUMPDEST 00000605: PUSH1 0x09 00000607: SLOAD 00000608: SWAP1 00000609: PUSH2 0x0963 0000060c: JUMP 0000060d: JUMPDEST 0000060e: PUSH1 0x09 00000610: SSTORE 00000611: JUMP 00000612: JUMPDEST 00000613: PUSH1 0x09 00000615: SLOAD 00000616: DUP2 00000617: JUMP 00000618: JUMPDEST 00000619: PUSH1 0x08 0000061b: SLOAD 0000061c: DUP2 0000061d: JUMP 0000061e: JUMPDEST 0000061f: PUSH2 0x0627 00000622: CALLER 00000623: PUSH2 0x062f 00000626: JUMP 00000627: JUMPDEST 00000628: JUMP 00000629: JUMPDEST 0000062a: PUSH1 0x0b 0000062c: SLOAD 0000062d: DUP2 0000062e: JUMP 0000062f: JUMPDEST 00000630: PUSH1 0x02 00000632: PUSH1 0x00 00000634: SLOAD 00000635: EQ 00000636: ISZERO 00000637: PUSH2 0x0687 0000063a: JUMPI 0000063b: PUSH1 0x40 0000063d: DUP1 0000063e: MLOAD 0000063f: PUSH3 0x461bcd 00000643: PUSH1 0xe5 00000645: SHL 00000646: DUP2 00000647: MSTORE 00000648: PUSH1 0x20 0000064a: PUSH1 0x04 0000064c: DUP3 0000064d: ADD 0000064e: MSTORE 0000064f: PUSH1 0x1f 00000651: PUSH1 0x24 00000653: DUP3 00000654: ADD 00000655: MSTORE 00000656: PUSH32 0x5265656e7472616e637947756172643a207265656e7472616e742063616c6c00 00000677: PUSH1 0x44 00000679: DUP3 0000067a: ADD 0000067b: MSTORE 0000067c: SWAP1 0000067d: MLOAD 0000067e: SWAP1 0000067f: DUP2 00000680: SWAP1 00000681: SUB 00000682: PUSH1 0x64 00000684: ADD 00000685: SWAP1 00000686: REVERT 00000687: JUMPDEST 00000688: PUSH1 0x02 0000068a: PUSH1 0x00 0000068c: SWAP1 0000068d: DUP2 0000068e: SSTORE 0000068f: PUSH1 0x01 00000691: PUSH1 0x01 00000693: PUSH1 0xa0 00000695: SHL 00000696: SUB 00000697: DUP3 00000698: AND 00000699: DUP2 0000069a: MSTORE 0000069b: PUSH1 0x05 0000069d: PUSH1 0x20 0000069f: MSTORE 000006a0: PUSH1 0x40 000006a2: SWAP1 000006a3: KECCAK256 000006a4: SLOAD 000006a5: PUSH2 0x06ad 000006a8: JUMPI 000006a9: PUSH2 0x07c2 000006ac: JUMP 000006ad: JUMPDEST 000006ae: PUSH1 0x00 000006b0: PUSH2 0x06b8 000006b3: DUP3 000006b4: PUSH2 0x0461 000006b7: JUMP 000006b8: JUMPDEST 000006b9: SWAP1 000006ba: POP 000006bb: DUP1 000006bc: ISZERO 000006bd: PUSH2 0x07c0 000006c0: JUMPI 000006c1: PUSH1 0x08 000006c3: SLOAD 000006c4: PUSH2 0x06cd 000006c7: SWAP1 000006c8: DUP3 000006c9: PUSH2 0x0963 000006cc: JUMP 000006cd: JUMPDEST 000006ce: PUSH1 0x08 000006d0: SSTORE 000006d1: PUSH1 0x40 000006d3: MLOAD 000006d4: PUSH1 0x01 000006d6: PUSH1 0x01 000006d8: PUSH1 0xa0 000006da: SHL 000006db: SUB 000006dc: DUP4 000006dd: AND 000006de: SWAP1 000006df: DUP3 000006e0: ISZERO 000006e1: PUSH2 0x08fc 000006e4: MUL 000006e5: SWAP1 000006e6: DUP4 000006e7: SWAP1 000006e8: PUSH1 0x00 000006ea: DUP2 000006eb: DUP2 000006ec: DUP2 000006ed: DUP6 000006ee: DUP9 000006ef: DUP9 000006f0: CALL 000006f1: SWAP4 000006f2: POP 000006f3: POP 000006f4: POP 000006f5: POP 000006f6: ISZERO 000006f7: DUP1 000006f8: ISZERO 000006f9: PUSH2 0x0706 000006fc: JUMPI 000006fd: RETURNDATASIZE 000006fe: PUSH1 0x00 00000700: DUP1 00000701: RETURNDATACOPY 00000702: RETURNDATASIZE 00000703: PUSH1 0x00 00000705: REVERT 00000706: JUMPDEST 00000707: POP 00000708: PUSH1 0x01 0000070a: PUSH1 0x01 0000070c: PUSH1 0xa0 0000070e: SHL 0000070f: SUB 00000710: DUP3 00000711: AND 00000712: PUSH1 0x00 00000714: SWAP1 00000715: DUP2 00000716: MSTORE 00000717: PUSH1 0x04 00000719: PUSH1 0x20 0000071b: SWAP1 0000071c: DUP2 0000071d: MSTORE 0000071e: PUSH1 0x40 00000720: DUP1 00000721: DUP4 00000722: KECCAK256 00000723: TIMESTAMP 00000724: SWAP1 00000725: SSTORE 00000726: PUSH1 0x05 00000728: SWAP1 00000729: SWAP2 0000072a: MSTORE 0000072b: SWAP1 0000072c: KECCAK256 0000072d: PUSH1 0x02 0000072f: ADD 00000730: SLOAD 00000731: PUSH2 0x073a 00000734: SWAP1 00000735: DUP3 00000736: PUSH2 0x0963 00000739: JUMP 0000073a: JUMPDEST 0000073b: PUSH1 0x01 0000073d: PUSH1 0x01 0000073f: PUSH1 0xa0 00000741: SHL 00000742: SUB 00000743: DUP4 00000744: AND 00000745: PUSH1 0x00 00000747: SWAP1 00000748: DUP2 00000749: MSTORE 0000074a: PUSH1 0x05 0000074c: PUSH1 0x20 0000074e: MSTORE 0000074f: PUSH1 0x40 00000751: SWAP1 00000752: KECCAK256 00000753: PUSH1 0x02 00000755: DUP2 00000756: ADD 00000757: SWAP2 00000758: SWAP1 00000759: SWAP2 0000075a: SSTORE 0000075b: SLOAD 0000075c: PUSH2 0x0764 0000075f: SWAP1 00000760: PUSH2 0x09bd 00000763: JUMP 00000764: JUMPDEST 00000765: PUSH1 0x01 00000767: PUSH1 0x01 00000769: PUSH1 0xa0 0000076b: SHL 0000076c: SUB 0000076d: DUP4 0000076e: AND 0000076f: PUSH1 0x00 00000771: DUP2 00000772: DUP2 00000773: MSTORE 00000774: PUSH1 0x05 00000776: PUSH1 0x20 00000778: SWAP1 00000779: DUP2 0000077a: MSTORE 0000077b: PUSH1 0x40 0000077d: SWAP2 0000077e: DUP3 0000077f: SWAP1 00000780: KECCAK256 00000781: PUSH1 0x01 00000783: ADD 00000784: SWAP4 00000785: SWAP1 00000786: SWAP4 00000787: SSTORE 00000788: DUP1 00000789: MLOAD 0000078a: SWAP2 0000078b: DUP3 0000078c: MSTORE 0000078d: SWAP2 0000078e: DUP2 0000078f: ADD 00000790: DUP4 00000791: SWAP1 00000792: MSTORE 00000793: DUP2 00000794: MLOAD 00000795: PUSH32 0x84fcdd4a7f507f2206dd50958e7473061bf941f91791c6ffaf74033a07c82f12 000007b6: SWAP3 000007b7: SWAP2 000007b8: DUP2 000007b9: SWAP1 000007ba: SUB 000007bb: SWAP1 000007bc: SWAP2 000007bd: ADD 000007be: SWAP1 000007bf: LOG1 000007c0: JUMPDEST 000007c1: POP 000007c2: JUMPDEST 000007c3: POP 000007c4: PUSH1 0x01 000007c6: PUSH1 0x00 000007c8: SSTORE 000007c9: JUMP 000007ca: JUMPDEST 000007cb: PUSH1 0x02 000007cd: DUP1 000007ce: SLOAD 000007cf: PUSH1 0x01 000007d1: PUSH1 0x01 000007d3: PUSH1 0xa0 000007d5: SHL 000007d6: SUB 000007d7: SWAP1 000007d8: SWAP3 000007d9: AND 000007da: PUSH1 0x00 000007dc: DUP2 000007dd: DUP2 000007de: MSTORE 000007df: PUSH1 0x03 000007e1: PUSH1 0x20 000007e3: MSTORE 000007e4: PUSH1 0x40 000007e6: DUP2 000007e7: KECCAK256 000007e8: DUP5 000007e9: SWAP1 000007ea: SSTORE 000007eb: PUSH1 0x01 000007ed: DUP5 000007ee: ADD 000007ef: DUP4 000007f0: SSTORE 000007f1: SWAP2 000007f2: SWAP1 000007f3: SWAP2 000007f4: MSTORE 000007f5: PUSH32 0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace 00000816: SWAP1 00000817: SWAP2 00000818: ADD 00000819: DUP1 0000081a: SLOAD 0000081b: PUSH1 0x01 0000081d: PUSH1 0x01 0000081f: PUSH1 0xa0 00000821: SHL 00000822: SUB 00000823: NOT 00000824: AND 00000825: SWAP1 00000826: SWAP2 00000827: OR 00000828: SWAP1 00000829: SSTORE 0000082a: JUMP 0000082b: JUMPDEST 0000082c: PUSH1 0x02 0000082e: DUP1 0000082f: SLOAD 00000830: PUSH1 0x00 00000832: NOT 00000833: DUP2 00000834: ADD 00000835: SWAP1 00000836: DUP2 00000837: LT 00000838: PUSH2 0x083d 0000083b: JUMPI 0000083c: INVALID 0000083d: JUMPDEST 0000083e: PUSH1 0x00 00000840: SWAP2 00000841: DUP3 00000842: MSTORE 00000843: PUSH1 0x20 00000845: DUP1 00000846: DUP4 00000847: KECCAK256 00000848: SWAP1 00000849: SWAP2 0000084a: ADD 0000084b: SLOAD 0000084c: PUSH1 0x01 0000084e: PUSH1 0x01 00000850: PUSH1 0xa0 00000852: SHL 00000853: SUB 00000854: DUP5 00000855: DUP2 00000856: AND 00000857: DUP5 00000858: MSTORE 00000859: PUSH1 0x03 0000085b: SWAP1 0000085c: SWAP3 0000085d: MSTORE 0000085e: PUSH1 0x40 00000860: SWAP1 00000861: SWAP3 00000862: KECCAK256 00000863: SLOAD 00000864: PUSH1 0x02 00000866: DUP1 00000867: SLOAD 00000868: SWAP3 00000869: SWAP1 0000086a: SWAP4 0000086b: AND 0000086c: SWAP3 0000086d: SWAP2 0000086e: DUP2 0000086f: LT 00000870: PUSH2 0x0875 00000873: JUMPI 00000874: INVALID 00000875: JUMPDEST 00000876: PUSH1 0x00 00000878: SWAP2 00000879: DUP3 0000087a: MSTORE 0000087b: PUSH1 0x20 0000087d: DUP1 0000087e: DUP4 0000087f: KECCAK256 00000880: SWAP2 00000881: SWAP1 00000882: SWAP2 00000883: ADD 00000884: DUP1 00000885: SLOAD 00000886: PUSH1 0x01 00000888: PUSH1 0x01 0000088a: PUSH1 0xa0 0000088c: SHL 0000088d: SUB 0000088e: NOT 0000088f: AND 00000890: PUSH1 0x01 00000892: PUSH1 0x01 00000894: PUSH1 0xa0 00000896: SHL 00000897: SUB 00000898: SWAP5 00000899: DUP6 0000089a: AND 0000089b: OR 0000089c: SWAP1 0000089d: SSTORE 0000089e: SWAP2 0000089f: DUP4 000008a0: AND 000008a1: DUP2 000008a2: MSTORE 000008a3: PUSH1 0x03 000008a5: SWAP2 000008a6: DUP3 000008a7: SWAP1 000008a8: MSTORE 000008a9: PUSH1 0x40 000008ab: DUP2 000008ac: KECCAK256 000008ad: SLOAD 000008ae: PUSH1 0x02 000008b0: DUP1 000008b1: SLOAD 000008b2: SWAP2 000008b3: SWAP4 000008b4: SWAP3 000008b5: SWAP2 000008b6: PUSH1 0x00 000008b8: NOT 000008b9: DUP2 000008ba: ADD 000008bb: SWAP1 000008bc: DUP2 000008bd: LT 000008be: PUSH2 0x08c3 000008c1: JUMPI 000008c2: INVALID 000008c3: JUMPDEST 000008c4: PUSH1 0x00 000008c6: SWAP2 000008c7: DUP3 000008c8: MSTORE 000008c9: PUSH1 0x20 000008cb: DUP1 000008cc: DUP4 000008cd: KECCAK256 000008ce: SWAP1 000008cf: SWAP2 000008d0: ADD 000008d1: SLOAD 000008d2: PUSH1 0x01 000008d4: PUSH1 0x01 000008d6: PUSH1 0xa0 000008d8: SHL 000008d9: SUB 000008da: AND 000008db: DUP4 000008dc: MSTORE 000008dd: DUP3 000008de: ADD 000008df: SWAP3 000008e0: SWAP1 000008e1: SWAP3 000008e2: MSTORE 000008e3: PUSH1 0x40 000008e5: ADD 000008e6: SWAP1 000008e7: KECCAK256 000008e8: SSTORE 000008e9: PUSH1 0x02 000008eb: DUP1 000008ec: SLOAD 000008ed: DUP1 000008ee: PUSH2 0x08f3 000008f1: JUMPI 000008f2: INVALID 000008f3: JUMPDEST 000008f4: PUSH1 0x00 000008f6: DUP3 000008f7: DUP2 000008f8: MSTORE 000008f9: PUSH1 0x20 000008fb: SWAP1 000008fc: KECCAK256 000008fd: DUP2 000008fe: ADD 000008ff: PUSH1 0x00 00000901: NOT 00000902: SWAP1 00000903: DUP2 00000904: ADD 00000905: DUP1 00000906: SLOAD 00000907: PUSH1 0x01 00000909: PUSH1 0x01 0000090b: PUSH1 0xa0 0000090d: SHL 0000090e: SUB 0000090f: NOT 00000910: AND 00000911: SWAP1 00000912: SSTORE 00000913: ADD 00000914: SWAP1 00000915: SSTORE 00000916: POP 00000917: JUMP 00000918: JUMPDEST 00000919: PUSH1 0x00 0000091b: PUSH2 0x095a 0000091e: DUP4 0000091f: DUP4 00000920: PUSH1 0x40 00000922: MLOAD 00000923: DUP1 00000924: PUSH1 0x40 00000926: ADD 00000927: PUSH1 0x40 00000929: MSTORE 0000092a: DUP1 0000092b: PUSH1 0x1e 0000092d: DUP2 0000092e: MSTORE 0000092f: PUSH1 0x20 00000931: ADD 00000932: PUSH32 0x536166654d6174683a207375627472616374696f6e206f766572666c6f770000 00000953: DUP2 00000954: MSTORE 00000955: POP 00000956: PUSH2 0x0a75 00000959: JUMP 0000095a: JUMPDEST 0000095b: SWAP1 0000095c: POP 0000095d: JUMPDEST 0000095e: SWAP3 0000095f: SWAP2 00000960: POP 00000961: POP 00000962: JUMP 00000963: JUMPDEST 00000964: PUSH1 0x00 00000966: DUP3 00000967: DUP3 00000968: ADD 00000969: DUP4 0000096a: DUP2 0000096b: LT 0000096c: ISZERO 0000096d: PUSH2 0x095a 00000970: JUMPI 00000971: PUSH1 0x40 00000973: DUP1 00000974: MLOAD 00000975: PUSH3 0x461bcd 00000979: PUSH1 0xe5 0000097b: SHL 0000097c: DUP2 0000097d: MSTORE 0000097e: PUSH1 0x20 00000980: PUSH1 0x04 00000982: DUP3 00000983: ADD 00000984: MSTORE 00000985: PUSH1 0x1b 00000987: PUSH1 0x24 00000989: DUP3 0000098a: ADD 0000098b: MSTORE 0000098c: PUSH32 0x536166654d6174683a206164646974696f6e206f766572666c6f770000000000 000009ad: PUSH1 0x44 000009af: DUP3 000009b0: ADD 000009b1: MSTORE 000009b2: SWAP1 000009b3: MLOAD 000009b4: SWAP1 000009b5: DUP2 000009b6: SWAP1 000009b7: SUB 000009b8: PUSH1 0x64 000009ba: ADD 000009bb: SWAP1 000009bc: REVERT 000009bd: JUMPDEST 000009be: PUSH1 0x00 000009c0: PUSH2 0x095d 000009c3: PUSH1 0x0a 000009c5: SLOAD 000009c6: PUSH2 0x05fe 000009c9: PUSH1 0x09 000009cb: SLOAD 000009cc: DUP6 000009cd: PUSH2 0x09da 000009d0: SWAP1 000009d1: SWAP2 000009d2: SWAP1 000009d3: PUSH4 0xffffffff 000009d8: AND 000009d9: JUMP 000009da: JUMPDEST 000009db: PUSH1 0x00 000009dd: DUP3 000009de: PUSH2 0x09e9 000009e1: JUMPI 000009e2: POP 000009e3: PUSH1 0x00 000009e5: PUSH2 0x095d 000009e8: JUMP 000009e9: JUMPDEST 000009ea: DUP3 000009eb: DUP3 000009ec: MUL 000009ed: DUP3 000009ee: DUP5 000009ef: DUP3 000009f0: DUP2 000009f1: PUSH2 0x09f6 000009f4: JUMPI 000009f5: INVALID 000009f6: JUMPDEST 000009f7: DIV 000009f8: EQ 000009f9: PUSH2 0x095a 000009fc: JUMPI 000009fd: PUSH1 0x40 000009ff: MLOAD 00000a00: PUSH3 0x461bcd 00000a04: PUSH1 0xe5 00000a06: SHL 00000a07: DUP2 00000a08: MSTORE 00000a09: PUSH1 0x04 00000a0b: ADD 00000a0c: DUP1 00000a0d: DUP1 00000a0e: PUSH1 0x20 00000a10: ADD 00000a11: DUP3 00000a12: DUP2 00000a13: SUB 00000a14: DUP3 00000a15: MSTORE 00000a16: PUSH1 0x21 00000a18: DUP2 00000a19: MSTORE 00000a1a: PUSH1 0x20 00000a1c: ADD 00000a1d: DUP1 00000a1e: PUSH2 0x0b72 00000a21: PUSH1 0x21 00000a23: SWAP2 00000a24: CODECOPY 00000a25: PUSH1 0x40 00000a27: ADD 00000a28: SWAP2 00000a29: POP 00000a2a: POP 00000a2b: PUSH1 0x40 00000a2d: MLOAD 00000a2e: DUP1 00000a2f: SWAP2 00000a30: SUB 00000a31: SWAP1 00000a32: REVERT 00000a33: JUMPDEST 00000a34: PUSH1 0x00 00000a36: PUSH2 0x095a 00000a39: DUP4 00000a3a: DUP4 00000a3b: PUSH1 0x40 00000a3d: MLOAD 00000a3e: DUP1 00000a3f: PUSH1 0x40 00000a41: ADD 00000a42: PUSH1 0x40 00000a44: MSTORE 00000a45: DUP1 00000a46: PUSH1 0x1a 00000a48: DUP2 00000a49: MSTORE 00000a4a: PUSH1 0x20 00000a4c: ADD 00000a4d: PUSH32 0x536166654d6174683a206469766973696f6e206279207a65726f000000000000 00000a6e: DUP2 00000a6f: MSTORE 00000a70: POP 00000a71: PUSH2 0x0b0c 00000a74: JUMP 00000a75: JUMPDEST 00000a76: PUSH1 0x00 00000a78: DUP2 00000a79: DUP5 00000a7a: DUP5 00000a7b: GT 00000a7c: ISZERO 00000a7d: PUSH2 0x0b04 00000a80: JUMPI 00000a81: PUSH1 0x40 00000a83: MLOAD 00000a84: PUSH3 0x461bcd 00000a88: PUSH1 0xe5 00000a8a: SHL 00000a8b: DUP2 00000a8c: MSTORE 00000a8d: PUSH1 0x04 00000a8f: ADD 00000a90: DUP1 00000a91: DUP1 00000a92: PUSH1 0x20 00000a94: ADD 00000a95: DUP3 00000a96: DUP2 00000a97: SUB 00000a98: DUP3 00000a99: MSTORE 00000a9a: DUP4 00000a9b: DUP2 00000a9c: DUP2 00000a9d: MLOAD 00000a9e: DUP2 00000a9f: MSTORE 00000aa0: PUSH1 0x20 00000aa2: ADD 00000aa3: SWAP2 00000aa4: POP 00000aa5: DUP1 00000aa6: MLOAD 00000aa7: SWAP1 00000aa8: PUSH1 0x20 00000aaa: ADD 00000aab: SWAP1 00000aac: DUP1 00000aad: DUP4 00000aae: DUP4 00000aaf: PUSH1 0x00 00000ab1: JUMPDEST 00000ab2: DUP4 00000ab3: DUP2 00000ab4: LT 00000ab5: ISZERO 00000ab6: PUSH2 0x0ac9 00000ab9: JUMPI 00000aba: DUP2 00000abb: DUP2 00000abc: ADD 00000abd: MLOAD 00000abe: DUP4 00000abf: DUP3 00000ac0: ADD 00000ac1: MSTORE 00000ac2: PUSH1 0x20 00000ac4: ADD 00000ac5: PUSH2 0x0ab1 00000ac8: JUMP 00000ac9: JUMPDEST 00000aca: POP 00000acb: POP 00000acc: POP 00000acd: POP 00000ace: SWAP1 00000acf: POP 00000ad0: SWAP1 00000ad1: DUP2 00000ad2: ADD 00000ad3: SWAP1 00000ad4: PUSH1 0x1f 00000ad6: AND 00000ad7: DUP1 00000ad8: ISZERO 00000ad9: PUSH2 0x0af6 00000adc: JUMPI 00000add: DUP1 00000ade: DUP3 00000adf: SUB 00000ae0: DUP1 00000ae1: MLOAD 00000ae2: PUSH1 0x01 00000ae4: DUP4 00000ae5: PUSH1 0x20 00000ae7: SUB 00000ae8: PUSH2 0x0100 00000aeb: EXP 00000aec: SUB 00000aed: NOT 00000aee: AND 00000aef: DUP2 00000af0: MSTORE 00000af1: PUSH1 0x20 00000af3: ADD 00000af4: SWAP2 00000af5: POP 00000af6: JUMPDEST 00000af7: POP 00000af8: SWAP3 00000af9: POP 00000afa: POP 00000afb: POP 00000afc: PUSH1 0x40 00000afe: MLOAD 00000aff: DUP1 00000b00: SWAP2 00000b01: SUB 00000b02: SWAP1 00000b03: REVERT 00000b04: JUMPDEST 00000b05: POP 00000b06: POP 00000b07: POP 00000b08: SWAP1 00000b09: SUB 00000b0a: SWAP1 00000b0b: JUMP 00000b0c: JUMPDEST 00000b0d: PUSH1 0x00 00000b0f: DUP2 00000b10: DUP4 00000b11: PUSH2 0x0b5b 00000b14: JUMPI 00000b15: PUSH1 0x40 00000b17: MLOAD 00000b18: PUSH3 0x461bcd 00000b1c: PUSH1 0xe5 00000b1e: SHL 00000b1f: DUP2 00000b20: MSTORE 00000b21: PUSH1 0x20 00000b23: PUSH1 0x04 00000b25: DUP3 00000b26: ADD 00000b27: DUP2 00000b28: DUP2 00000b29: MSTORE 00000b2a: DUP4 00000b2b: MLOAD 00000b2c: PUSH1 0x24 00000b2e: DUP5 00000b2f: ADD 00000b30: MSTORE 00000b31: DUP4 00000b32: MLOAD 00000b33: SWAP1 00000b34: SWAP3 00000b35: DUP4 00000b36: SWAP3 00000b37: PUSH1 0x44 00000b39: SWAP1 00000b3a: SWAP2 00000b3b: ADD 00000b3c: SWAP2 00000b3d: SWAP1 00000b3e: DUP6 00000b3f: ADD 00000b40: SWAP1 00000b41: DUP1 00000b42: DUP4 00000b43: DUP4 00000b44: PUSH1 0x00 00000b46: DUP4 00000b47: ISZERO 00000b48: PUSH2 0x0ac9 00000b4b: JUMPI 00000b4c: DUP2 00000b4d: DUP2 00000b4e: ADD 00000b4f: MLOAD 00000b50: DUP4 00000b51: DUP3 00000b52: ADD 00000b53: MSTORE 00000b54: PUSH1 0x20 00000b56: ADD 00000b57: PUSH2 0x0ab1 00000b5a: JUMP 00000b5b: JUMPDEST 00000b5c: POP 00000b5d: PUSH1 0x00 00000b5f: DUP4 00000b60: DUP6 00000b61: DUP2 00000b62: PUSH2 0x0b67 00000b65: JUMPI 00000b66: INVALID 00000b67: JUMPDEST 00000b68: DIV 00000b69: SWAP6 00000b6a: SWAP5 00000b6b: POP 00000b6c: POP 00000b6d: POP 00000b6e: POP 00000b6f: POP 00000b70: JUMP 00000b71: INVALID 00000b72: MSTORE8 00000b73: PUSH2 0x6665 00000b76: UNKNOWN(0x4D) 00000b77: PUSH2 0x7468 00000b7a: GASPRICE 00000b7b: KECCAK256 00000b7c: PUSH14 0x756c7469706c69636174696f6e20 00000b8b: PUSH16 0x766572666c6f77a26469706673582212 00000b9c: KECCAK256 00000b9d: SWAP9 00000b9e: UNKNOWN(0xCD) 00000b9f: UNKNOWN(0xAF) 00000ba0: CALLCODE 00000ba1: ADDRESS 00000ba2: BASEFEE 00000ba3: MCOPY 00000ba4: UNKNOWN(0xFC) 00000ba5: JUMPDEST 00000ba6: SWAP9 00000ba7: UNKNOWN(0xFC) 00000ba8: UNKNOWN(0xC1) 00000ba9: SELFBALANCE 00000baa: UNKNOWN(0xB0) 00000bab: BLOBBASEFEE 00000bac: UNKNOWN(0xB1) 00000bad: UNKNOWN(0xA6) 00000bae: SHR 00000baf: UNKNOWN(0xA8) 00000bb0: PUSH21 0x3a89f106e482b0ad51a90f9464736f6c634300060c 00000bc6: STOP 00000bc7: CALLER
| Severity | Category | Tool | Title | Confidence | Validated | Confirmed | Details |
|---|---|---|---|---|---|---|---|
| high | other | detector | Untrusted CALL target/value reachable | 60 | no | no |
viewtrace_id: 0xe88605fa94361b0a8d2e987a5c2da8a9a10333d3c8d0d402b5b7b9c63ad0b58a
call_targets:
0x50c2954613e70294088c7001d6f4a641f155b369
target_varies:
no
classification:
constant_target
validation_json{
"sink": "CALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0xe88605fa94361b0a8d2e987a5c2da8a9a10333d3c8d0d402b5b7b9c63ad0b58a",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x50c2954613e70294088c7001d6f4a641f155b369"
],
"matched_probe": null,
"target_varies": false,
"classification": "constant_target"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0xe2d2e219",
"selector": "0xe2d2e219",
"calldata_variants": [
"0xe2d2e219",
"0xe2d2e2190000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xefca2eed",
"selector": "0xefca2eed",
"calldata_variants": [
"0xefca2eed",
"0xefca2eed0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xf0fc6bca",
"selector": "0xf0fc6bca",
"calldata_variants": [
"0xf0fc6bca",
"0xf0fc6bca0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xffd49c84",
"selector": "0xffd49c84",
"calldata_variants": [
"0xffd49c84",
"0xffd49c840000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0x997664d7",
"selector": "0x997664d7",
"calldata_variants": [
"0x997664d7",
"0x997664d70000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xabd37753",
"selector": "0xabd37753",
"calldata_variants": [
"0xabd37753",
"0xabd377530000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xce7c2ac2",
"selector": "0xce7c2ac2",
"calldata_variants": [
"0xce7c2ac2",
"0xce7c2ac20000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xd0e30db0",
"selector": "0xd0e30db0",
"calldata_variants": [
"0xd0e30db0",
"0xd0e30db00000000000000000000000000000000000000000000000000000000000000000"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 1776,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 2976,
"opcode": "CALLCODE",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"call_count": 2,
"guards_detected": [],
"untrusted_call_count": 2
}
|
| high | other | detector | ETH value transfer possible | 55 | no | no |
viewtrace_id: 0xe88605fa94361b0a8d2e987a5c2da8a9a10333d3c8d0d402b5b7b9c63ad0b58a
call_targets:
0x50c2954613e70294088c7001d6f4a641f155b369
target_varies:
no
classification:
constant_target
validation_json{
"sink": "CALL",
"errors": 0,
"status": "sink_reached",
"attempts": 1,
"trace_id": "0xe88605fa94361b0a8d2e987a5c2da8a9a10333d3c8d0d402b5b7b9c63ad0b58a",
"confirmed": false,
"trace_mode": "callTracer",
"call_targets": [
"0x50c2954613e70294088c7001d6f4a641f155b369"
],
"matched_probe": null,
"target_varies": false,
"classification": "constant_target"
}
witness_json{
"notes": "heuristic witness; entrypoints are best-effort selectors with zeroed calldata",
"constraints": [],
"entrypoints": [
{
"calldata": "0xe2d2e219",
"selector": "0xe2d2e219",
"calldata_variants": [
"0xe2d2e219",
"0xe2d2e2190000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xefca2eed",
"selector": "0xefca2eed",
"calldata_variants": [
"0xefca2eed",
"0xefca2eed0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xf0fc6bca",
"selector": "0xf0fc6bca",
"calldata_variants": [
"0xf0fc6bca",
"0xf0fc6bca0000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xffd49c84",
"selector": "0xffd49c84",
"calldata_variants": [
"0xffd49c84",
"0xffd49c840000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0x997664d7",
"selector": "0x997664d7",
"calldata_variants": [
"0x997664d7",
"0x997664d70000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xabd37753",
"selector": "0xabd37753",
"calldata_variants": [
"0xabd37753",
"0xabd377530000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xce7c2ac2",
"selector": "0xce7c2ac2",
"calldata_variants": [
"0xce7c2ac2",
"0xce7c2ac20000000000000000000000000000000000000000000000000000000000000000"
]
},
{
"calldata": "0xd0e30db0",
"selector": "0xd0e30db0",
"calldata_variants": [
"0xd0e30db0",
"0xd0e30db00000000000000000000000000000000000000000000000000000000000000000"
]
}
]
}
evidence_json{
"examples": [
{
"pc": 1776,
"opcode": "CALL",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
},
{
"pc": 2976,
"opcode": "CALLCODE",
"returndata_checked": null,
"value_expression_category": "computed",
"target_expression_category": "computed"
}
],
"eth_value_calls": 2,
"guards_detected": []
}
|
| low | other | codex | Reverting shareholder contracts can block share updates | 65 | no | — |
viewevidence_json{
"evidence": "`setShare()` unconditionally calls `distributeDividend()` for existing holders before mutating balances. `distributeDividend()` then uses `shareholder.transfer(amount)`, which reverts for non-payable or gas-heavy recipients and therefore reverts the entire share update.",
"locations": [
"contracts/external/DividendDistributor.sol:61",
"contracts/external/DividendDistributor.sol:62",
"contracts/external/DividendDistributor.sol:95"
],
"recommendation": "Do not make share bookkeeping depend on a push-payment succeeding. Prefer a pull-based withdrawal model, or use a low-level call and record failed payouts so `setShare` can still complete.",
"exploit_scenario": "A holder can own shares through a contract account whose `receive`/fallback always reverts or needs more than 2300 gas. Once that holder has unpaid earnings, any later `setShare(holder, ...)` call first tries to pay them via `transfer()`. That payout revert bubbles up and aborts `setShare`, so any parent token flow that updates shares during transfers/sells can no longer modify that holder\u2019s position."
}
|
| low | math | codex | Deposits revert when no shares exist | 65 | no | — |
viewevidence_json{
"evidence": "`deposit()` computes `msg.value / totalShares` without validating that `totalShares` is non-zero. `totalShares` starts at zero and is adjusted directly by `setShare()`, including down to zero when the last holder is removed.",
"locations": [
"contracts/external/DividendDistributor.sol:79",
"contracts/external/DividendDistributor.sol:82",
"contracts/external/DividendDistributor.sol:71"
],
"recommendation": "Guard `deposit()` with a `totalShares > 0` check and either reject upstream calls earlier or hold pending ETH until shares exist.",
"exploit_scenario": "If the parent token calls `deposit()` before any shareholder has been registered, or after all shareholders have been removed, the function divides by `totalShares == 0` and hard-reverts. In integrations that call the distributor during automated fee processing, that can temporarily DoS the upstream fee/swap path until a non-zero share exists again."
}
|